1  /-
  2  Copyright (c) 2018 Mario Carneiro. All rights reserved.
  3  Released under Apache 2.0 license as described in the file LICENSE.
  4  Author: Mario Carneiro
  5  
  6  Define a sequence of simple machine languages, starting with Turing
  7  machines and working up to more complex lanaguages based on
  8  Wang B-machines.
  9  -/
 10  import data.fintype data.pfun logic.relation
src         └──────────┘ └───────┘ └────────────┘
 11  
 12  open relation
 13  
 14  namespace turing
 15  
 16  /-- A direction for the turing machine `move` command, either
 17    left or right. -/
 18  @[derive decidable_eq, derive inhabited]
id            └──────────┘         └───────┘
src           └──────────┘         └───────┘
typ           └──────────┘         └───────┘
doc    └────┘               └────┘
 19  inductive dir | left | right
 20  
 21  def tape (Γ) := Γ × list Γ × list Γ
id                     └──┘   └──┘ 
src                     └──┘    └──┘
typ                    └──┘   └──┘ 
 22  
 23  instance {Γ} [inhabited Γ] : inhabited (tape Γ) :=
id                 └───────┘     └───────┘  └──┘ 
src                └───────┘      └───────┘  └──┘
typ                └───────┘     └───────┘  └──┘ 
 24  ⟨by constructor; apply default⟩
id                          └─────┘
src      └─────────┘  └────┘└─────┘
typ      └─────────┘  └────┘└─────┘
doc      └─────────┘  └────┘
txt      └─────────┘  └────┘
par      └─────────┘  └────┘
pid                        
st      └─────────────────────────┘
 25  
 26  def tape.mk {Γ} [inhabited Γ] (l : list Γ) : tape Γ :=
id                    └───────┘        └──┘     └──┘ 
src                   └───────┘         └──┘      └──┘
typ                   └───────┘        └──┘     └──┘ 
 27  (l.head, [], l.tail)
id   └───┘  └┘  └───┘
src   └───┘  └┘   └───┘
typ  └───┘  └┘  └───┘
 28  
 29  def tape.mk' {Γ} [inhabited Γ] (L R : list Γ) : tape Γ :=
id                     └───────┘          └──┘     └──┘ 
src                    └───────┘           └──┘      └──┘
typ                    └───────┘          └──┘     └──┘ 
 30  (R.head, L, R.tail)
id   └───┘    └───┘
src   └───┘      └───┘
typ  └───┘    └───┘
 31  
 32  def tape.move {Γ} [inhabited Γ] : dir → tape Γ → tape Γ
id                      └───────┘     └─┘  └──┘    └──┘ 
src                     └───────┘      └─┘   └──┘     └──┘
typ                     └───────┘     └─┘  └──┘    └──┘ 
doc                                    └─┘
 33  | dir.left (a, L, R) := (L.head, L.tail, a :: R)
id     └──────┘           └───┘   └───┘    └┘
src    └──────┘              └───┘   └───┘    └┘
typ    └──────┘           └───┘   └───┘    └┘
 34  | dir.right (a, L, R) := (R.head, a :: L, R.tail)
id     └───────┘           └───┘    └┘     └───┘
src    └───────┘              └───┘    └┘     └───┘
typ    └───────┘           └───┘    └┘     └───┘
 35  
 36  def tape.nth {Γ} [inhabited Γ] : tape Γ → ℤ → Γ
id                     └───────┘     └──┘      
src                    └───────┘      └──┘     
typ                    └───────┘     └──┘      
 37  | (a, L, R) 0 := a
id     
src    
typ    
 38  | (a, L, R) (n+1:ℕ) := R.inth n
id                      └───┘
src                       └───┘
typ                     └───┘
doc                          └───┘
st     
 39  | (a, L, R) -[1+ n] := L.inth n
id             └──┘      └───┘
src             └──┘       └───┘
typ            └──┘      └───┘
doc                          └───┘
 40  
 41  @[simp] theorem tape.nth_zero {Γ} [inhabited Γ] :
id                                      └───────┘ 
src                                     └───────┘
typ                                     └───────┘ 
doc    └──┘
 42    ∀ (T : tape Γ), T.nth 0 = T.1
id           └──┘    └──┘    
src           └──┘      └──┘     
typ          └──┘    └──┘    
 43  | (a, L, R) := rfl
id                 └─┘
src                └─┘
typ                └─┘
 44  
 45  @[simp] theorem tape.move_left_nth {Γ} [inhabited Γ] :
id                                           └───────┘ 
src                                          └───────┘
typ                                          └───────┘ 
doc    └──┘
 46    ∀ (T : tape Γ) (i : ℤ), (T.move dir.left).nth i = T.nth (i-1)
id           └──┘            └───┘ └──────┘ └─┘    └──┘  
src           └──┘              └───┘ └──────┘ └─┘      └──┘   
typ          └──┘            └───┘ └──────┘ └─┘    └──┘  
 47  | (a, L, R) -[1+ n]      := by cases L; refl
id              └──┘                    
src             └──┘              └────┘   └───┘
typ             └──┘              └────┘  └───┘
doc                                 └────┘   └───┘
txt                                 └────┘   └───┘
par                                 └────┘   └───┘
pid                                             
st                                 └─────────────┘
 48  | (a, L, R) 0           := by cases L; refl
id                                      
src                               └────┘   └───┘
typ                               └────┘  └───┘
doc                                └────┘   └───┘
txt                                └────┘   └───┘
par                                └────┘   └───┘
pid                                            
st                                └─────────────┘
 49  | (a, L, R) 1           := rfl
id                             └─┘
src                            └─┘
typ                            └─┘
 50  | (a, L, R) ((n+1:ℕ)+1) := by rw add_sub_cancel; refl
id                                └────────────┘
src                            └─┘└────────────┘  └────
typ                            └─┘└────────────┘  └────
doc                                └─┘                └────
txt                                └─┘                └────
par                                └─┘                └────
pid                                                      
st                                └────────────────────────
 51  
src  
typ  
doc  
txt  
par  
pid  
st   
 52  @[simp] theorem tape.move_right_nth {Γ} [inhabited Γ] :
id                                            └───────┘ 
src                                           └───────┘
typ                                           └───────┘ 
doc    └──┘
 53    ∀ (T : tape Γ) (i : ℤ), (T.move dir.right).nth i = T.nth (i+1)
id           └──┘            └───┘ └───────┘ └─┘    └──┘  
src           └──┘              └───┘ └───────┘ └─┘      └──┘   
typ          └──┘            └───┘ └───────┘ └─┘    └──┘  
 54  | (a, L, R) (n+1:ℕ)    := by cases R; refl
id                                   
src                            └────┘   └───┘
typ                            └────┘  └───┘
doc                               └────┘   └───┘
txt                               └────┘   └───┘
par                               └────┘   └───┘
pid                                           
st                               └─────────────┘
 55  | (a, L, R) 0         := by cases R; refl
id                                    
src                             └────┘   └───┘
typ                             └────┘  └───┘
doc                              └────┘   └───┘
txt                              └────┘   └───┘
par                              └────┘   └───┘
pid                                          
st                              └─────────────┘
 56  | (a, L, R) -1        := rfl
id                          └─┘
src                         └─┘
typ                         └─┘
 57  | (a, L, R) -[1+ n+1] := show _ = tape.nth _ (-[1+ n] - 1 + 1),
id              └──┘              └──────┘    └──┘      
src             └──┘               └──────┘    └──┘      
typ             └──┘              └──────┘    └──┘      
 58    by rw sub_add_cancel; refl
id           └────────────┘
src       └─┘└────────────┘  └────
typ       └─┘└────────────┘  └────
doc       └─┘                └────
txt       └─┘                └────
par       └─┘                └────
pid                             
st       └────────────────────────
 59  
src  
typ  
doc  
txt  
par  
pid  
st   
 60  def tape.write {Γ} (b : Γ) : tape Γ → tape Γ
id                               └──┘   └──┘ 
src                               └──┘     └──┘
typ                              └──┘   └──┘ 
 61  | (a, LR) := (b, LR)
id        └┘     
src              
typ       └┘     
 62  
 63  @[simp] theorem tape.write_self {Γ} : ∀ (T : tape Γ), T.write T.1 = T
id                                               └──┘    └────┘    
src                                               └──┘      └────┘    
typ                                              └──┘    └────┘    
doc    └──┘
 64  | (a, LR) := rfl
id               └─┘
src              └─┘
typ              └─┘
 65  
 66  @[simp] theorem tape.write_nth {Γ} [inhabited Γ] (b : Γ) :
id                                       └───────┘        
src                                      └───────┘
typ                                      └───────┘        
doc    └──┘
 67    ∀ (T : tape Γ) {i : ℤ}, (T.write b).nth i = if i = 0 then b else T.nth i
id           └──┘            └────┘  └─┘                      └──┘ 
src           └──┘              └────┘   └─┘                          └──┘
typ          └──┘            └────┘  └─┘                      └──┘ 
 68  | (a, L, R) 0       := rfl
id                         └─┘
src                        └─┘
typ                        └─┘
 69  | (a, L, R) (n+1:ℕ) := rfl
id                       └─┘
src                      └─┘
typ                      └─┘
 70  | (a, L, R) -[1+ n] := rfl
id              └──┘      └─┘
src             └──┘      └─┘
typ             └──┘      └─┘
 71  
 72  def tape.map {Γ Γ'} (f : Γ → Γ') : tape Γ → tape Γ'
id                               └┘    └──┘   └──┘ └┘
src                                     └──┘     └──┘
typ                              └┘    └──┘   └──┘ └┘
 73  | (a, L, R) := (f a, L.map f, R.map f)
id                   └──┘    └──┘ 
src                      └──┘     └──┘
typ                  └──┘    └──┘ 
 74  
 75  @[simp] theorem tape.map_fst {Γ Γ'} (f : Γ → Γ') : ∀ (T : tape Γ), (T.map f).1 = f T.1
id                                               └┘          └──┘     └──┘      
src                                                            └──┘       └──┘         
typ                                              └┘          └──┘     └──┘      
doc    └──┘
 76  | (a, L, R) := rfl
id                 └─┘
src                └─┘
typ                └─┘
 77  
 78  @[simp] theorem tape.map_write {Γ Γ'} (f : Γ → Γ') (b : Γ) :
id                                                 └┘       
typ                                                └┘       
doc    └──┘
 79    ∀ (T : tape Γ), (T.write b).map f = (T.map f).write (f b)
id           └──┘     └────┘  └─┘     └──┘  └───┘    
src           └──┘       └────┘   └─┘       └──┘   └───┘
typ          └──┘     └────┘  └─┘     └──┘  └───┘    
 80  | (a, L, R) := rfl
id                 └─┘
src                └─┘
typ                └─┘
 81  
 82  @[class] def pointed_map {Γ Γ'} [inhabited Γ] [inhabited Γ'] (f : Γ → Γ') :=
id                                    └───────┘    └───────┘ └┘          └┘
src                                   └───────┘     └───────┘
typ                                   └───────┘    └───────┘ └┘          └┘
 83  f (default _) = default _
id     └─────┘     └─────┘
src     └─────┘     └─────┘
typ    └─────┘     └─────┘
 84  
 85  theorem tape.map_move {Γ Γ'} [inhabited Γ] [inhabited Γ']
id                                 └───────┘    └───────┘ └┘
src                                └───────┘     └───────┘
typ                                └───────┘    └───────┘ └┘
 86    (f : Γ → Γ') [pointed_map f] :
id             └┘   └─────────┘ 
src                  └─────────┘
typ            └┘   └─────────┘ 
 87    ∀ (T : tape Γ) d, (T.move d).map f = (T.map f).move d
id           └──┘      └───┘  └─┘     └──┘  └──┘  
src           └──┘         └───┘   └─┘       └──┘   └──┘
typ          └──┘      └───┘  └─┘     └──┘  └──┘  
 88  | (a, [],   R) dir.left  := prod.ext ‹pointed_map f› rfl
id        └┘       └──────┘     └──────┘ └─────────┘  └─┘
src       └┘       └──────┘     └──────┘ └─────────┘   └─┘
typ       └┘       └──────┘     └──────┘ └─────────┘  └─┘
doc                                                    
 89  | (a, b::L, R) dir.left  := rfl
id         └┘      └──────┘     └─┘
src        └┘      └──────┘     └─┘
typ        └┘      └──────┘     └─┘
 90  | (a, L, [])   dir.right := prod.ext ‹pointed_map f› rfl
id           └┘    └───────┘    └──────┘ └─────────┘  └─┘
src          └┘    └───────┘    └──────┘ └─────────┘   └─┘
typ          └┘    └───────┘    └──────┘ └─────────┘  └─┘
doc                                                    
 91  | (a, L, b::R) dir.right := rfl
id            └┘   └───────┘    └─┘
src           └┘   └───────┘    └─┘
typ           └┘   └───────┘    └─┘
 92  
 93  theorem tape.map_mk {Γ Γ'} [inhabited Γ] [inhabited Γ']
id                               └───────┘    └───────┘ └┘
src                              └───────┘     └───────┘
typ                              └───────┘    └───────┘ └┘
 94    (f : Γ → Γ') [f0 : pointed_map f] :
id             └┘        └─────────┘ 
src                       └─────────┘
typ            └┘        └─────────┘ 
 95    ∀ (l : list Γ), (tape.mk l).map f = tape.mk (l.map f)
id           └──┘     └─────┘  └─┘    └─────┘  └──┘ 
src           └──┘      └─────┘   └─┘     └─────┘   └──┘
typ          └──┘     └─────┘  └─┘    └─────┘  └──┘ 
 96  | []     := prod.ext ‹pointed_map f› rfl
id     └┘        └──────┘ └─────────┘  └─┘
src    └┘        └──────┘ └─────────┘   └─┘
typ    └┘        └──────┘ └─────────┘  └─┘
doc                                    
 97  | (a::l) := rfl
id       └┘      └─┘
src      └┘      └─┘
typ      └┘      └─┘
 98  
 99  def eval {σ} (f : σ → option σ) : σ → roption σ :=
id                        └────┘        └─────┘ 
src                        └────┘          └─────┘
typ                       └────┘        └─────┘ 
doc                                        └─────┘
100  pfun.fix (λ s, roption.some $
id   └──────┘      └──────────┘
src  └──────┘       └──────────┘
typ  └──────┘      └──────────┘
doc                 └──────────┘
101    match f s with none := sum.inl s | some s' := sum.inr s' end)
id                  └──┘    └─────┘    └──┘ └┘    └─────┘
src                   └──┘    └─────┘     └──┘       └─────┘
typ                 └──┘    └─────┘    └──┘ └┘    └─────┘
102  
103  def reaches {σ} (f : σ → option σ) : σ → σ → Prop :=
id                           └────┘        
src                           └────┘
typ                          └────┘        
104  refl_trans_gen (λ a b, b ∈ f a)
id   └────────────┘          
src  └────────────┘           
typ  └────────────┘          
doc  └────────────┘
st                                  
105  
106  def reaches₁ {σ} (f : σ → option σ) : σ → σ → Prop :=
id                            └────┘        
src                            └────┘
typ                           └────┘        
107  trans_gen (λ a b, b ∈ f a)
id   └───────┘          
src  └───────┘           
typ  └───────┘          
doc  └───────┘
108  
109  theorem reaches₁_eq {σ} {f : σ → option σ} {a b c}
id                                   └────┘ 
src                                   └────┘
typ                                  └────┘ 
110    (h : f a = f b) : reaches₁ f a c ↔ reaches₁ f b c :=
id                  └──────┘     └──────┘   
src                     └──────┘        └──────┘
typ                 └──────┘     └──────┘   
111  trans_gen.head'_iff.trans (trans_gen.head'_iff.trans $ by rw h).symm
id   └─────────────────┘└────┘  └─────────────────┘└────┘          └──┘
src  └─────────────────┘└────┘  └─────────────────┘└────┘      └─┘  └──┘
typ  └─────────────────┘└────┘  └─────────────────┘└────┘      └─┘ └──┘
doc                                                            └─┘
txt                                                            └─┘
par                                                            └─┘
pid                                                              
st                                                            └───┘
112  
113  theorem reaches_total {σ} {f : σ → option σ}
id                                     └────┘ 
src                                     └────┘
typ                                    └────┘ 
114    {a b c} : reaches f a b → reaches f a c →
id               └─────┘      └─────┘   
src              └─────┘         └─────┘
typ              └─────┘      └─────┘   
115    reaches f b c ∨ reaches f c b :=
id     └─────┘     └─────┘   
src    └─────┘        └─────┘
typ    └─────┘     └─────┘   
116  refl_trans_gen.total_of_right_unique $ λ _ _ _, option.mem_unique
id   └──────────────────────────────────┘         └───────────────┘
src  └──────────────────────────────────┘            └───────────────┘
typ  └──────────────────────────────────┘         └───────────────┘
117  
118  theorem reaches₁_fwd {σ} {f : σ → option σ}
id                                    └────┘ 
src                                    └────┘
typ                                   └────┘ 
119    {a b c} (h₁ : reaches₁ f a c) (h₂ : b ∈ f a) : reaches f b c :=
id                   └──────┘                  └─────┘   
src                  └──────┘                        └─────┘
typ                  └──────┘                  └─────┘   
120  begin
st   └─────
121    rcases trans_gen.head'_iff.1 h₁ with ⟨b', hab, hbc⟩,
id            └─────────────────┘   └┘
src    └─────┘└─────────────────┘└─┘  └──────────────────┘
typ    └─────┘└─────────────────┘└─┘└┘└──────────────────┘
doc    └─────┘                   └─┘  └──────────────────┘
txt    └─────┘                   └─┘  └──────────────────┘
par    └─────┘                   └─┘  └──────────────────┘
pid                             └─┘  └──────────────────┘
st   ────────────────────────────────────────────────────┘└─
122    cases option.mem_unique hab h₂, exact hbc
id           └───────────────┘ └─┘ └┘        └─┘
src    └────┘└───────────────┘       └────┘   
typ    └────┘└───────────────┘└─┘└┘  └────┘└─┘
doc    └────┘                        └────┘   
txt    └────┘                        └────┘   
par    └────┘                        └────┘   
pid                                         
st   ───────────────────────────────┘└──────────┘
123  end
st   └─┘
124  
125  def reaches₀ {σ} (f : σ → option σ) (a b : σ) : Prop :=
id                            └────┘          
src                            └────┘
typ                           └────┘          
126  ∀ c, reaches₁ f b c → reaches₁ f a c
id       └──────┘      └──────┘   
src       └──────┘         └──────┘
typ      └──────┘      └──────┘   
127  
128  theorem reaches₀.trans {σ} {f : σ → option σ} {a b c : σ}
id                                      └────┘            
src                                      └────┘
typ                                     └────┘            
129    (h₁ : reaches₀ f a b) (h₂ : reaches₀ f b c) : reaches₀ f a c
id           └──────┘           └──────┘       └──────┘   
src          └──────┘              └──────┘          └──────┘
typ          └──────┘           └──────┘       └──────┘   
130  | d h₃ := h₁ _ (h₂ _ h₃)
id       └┘    └┘    └┘
typ      └┘    └┘    └┘
131  
132  @[refl] theorem reaches₀.refl {σ} {f : σ → option σ} (a : σ) : reaches₀ f a a
id                                             └────┘            └──────┘   
src    └──┘                                     └────┘              └──────┘
typ                                            └────┘            └──────┘   
doc    └──┘
133  | b h := h
id       
typ      
134  
135  theorem reaches₀.single {σ} {f : σ → option σ} {a b : σ}
id                                       └────┘          
src                                       └────┘
typ                                      └────┘          
136    (h : b ∈ f a) : reaches₀ f a b
id                 └──────┘   
src                   └──────┘
typ                └──────┘   
137  | c h₂ := h₂.head h
id       └┘      └───┘ 
src              └───┘
typ      └┘      └───┘ 
138  
139  theorem reaches₀.head {σ} {f : σ → option σ} {a b c : σ}
id                                     └────┘            
src                                     └────┘
typ                                    └────┘            
140    (h : b ∈ f a) (h₂ : reaches₀ f b c) : reaches₀ f a c :=
id                     └──────┘       └──────┘   
src                       └──────┘          └──────┘
typ                    └──────┘       └──────┘   
141  (reaches₀.single h).trans h₂
id    └─────────────┘  └───┘  └┘
src   └─────────────┘   └───┘
typ   └─────────────┘  └───┘  └┘
142  
143  theorem reaches₀.tail {σ} {f : σ → option σ} {a b c : σ}
id                                     └────┘            
src                                     └────┘
typ                                    └────┘            
144    (h₁ : reaches₀ f a b) (h : c ∈ f b) : reaches₀ f a c :=
id           └──────┘                 └──────┘   
src          └──────┘                       └──────┘
typ          └──────┘                 └──────┘   
145  h₁.trans (reaches₀.single h)
id   └┘└────┘  └─────────────┘ 
src    └────┘  └─────────────┘
typ  └┘└────┘  └─────────────┘ 
146  
147  theorem reaches₀_eq {σ} {f : σ → option σ} {a b}
id                                   └────┘ 
src                                   └────┘
typ                                  └────┘ 
148    (e : f a = f b) : reaches₀ f a b
id                  └──────┘   
src                     └──────┘
typ                 └──────┘   
149  | d h := (reaches₁_eq e).2 h
id            └─────────┘  
src            └─────────┘   
typ           └─────────┘  
150  
151  theorem reaches₁.to₀ {σ} {f : σ → option σ} {a b : σ}
id                                    └────┘          
src                                    └────┘
typ                                   └────┘          
152    (h : reaches₁ f a b) : reaches₀ f a b
id          └──────┘       └──────┘   
src         └──────┘          └──────┘
typ         └──────┘       └──────┘   
153  | c h₂ := h.trans h₂
id       └┘    └────┘
src             └────┘
typ      └┘    └────┘
154  
155  theorem reaches.to₀ {σ} {f : σ → option σ} {a b : σ}
id                                   └────┘          
src                                   └────┘
typ                                  └────┘          
156    (h : reaches f a b) : reaches₀ f a b
id          └─────┘       └──────┘   
src         └─────┘          └──────┘
typ         └─────┘       └──────┘   
157  | c h₂ := h₂.trans_right h
id       └┘      └──────────┘ 
src              └──────────┘
typ      └┘      └──────────┘ 
158  
159  theorem reaches₀.tail' {σ} {f : σ → option σ} {a b c : σ}
id                                      └────┘            
src                                      └────┘
typ                                     └────┘            
160    (h : reaches₀ f a b) (h₂ : c ∈ f b) : reaches₁ f a c :=
id          └──────┘                  └──────┘   
src         └──────┘                        └──────┘
typ         └──────┘                  └──────┘   
161  h _ (trans_gen.single h₂)
id       └──────────────┘ └┘
src       └──────────────┘
typ      └──────────────┘ └┘
162  
163  theorem mem_eval {σ} {f : σ → option σ} {a b} :
id                                └────┘ 
src                                └────┘
typ                               └────┘ 
164    b ∈ eval f a ↔ reaches f a b ∧ f b = none :=
id       └──┘    └─────┘        └──┘
src       └──┘      └─────┘             └──┘
typ      └──┘    └─────┘        └──┘
165  ⟨λ h, begin
id      
typ     
st         └─────
166    refine pfun.fix_induction h (λ a h IH, _),
id            └────────────────┘ 
src    └─────┘└────────────────┘   └─────────┘
typ    └─────┘└────────────────┘  └─────────┘
doc    └─────┘                     └─────────┘
txt    └─────┘                     └─────────┘
par    └─────┘                     └─────────┘
pid                               └─────────┘
st   ──────────────────────────────────────────┘└─
167    cases e : f a with a',
id                
src    └────┘ └─┘  └──────┘
typ    └────┘ └─┘└──────┘
doc    └────┘ └─┘  └──────┘
txt    └────┘ └─┘  └──────┘
par    └────┘ └─┘  └──────┘
pid          └─┘  └──────┘
st   ──────────────────────┘└─
168    { rw roption.mem_unique h (pfun.mem_fix_iff.2 $ or.inl $
id          └────────────────┘   └──────────────┘     └────┘
src      └─┘└────────────────┘  └──────────────┘└─┘ └────┘ 
typ      └─┘└────────────────┘ └──────────────┘└─┘ └────┘ 
doc      └─┘                                    └─┘        
txt      └─┘                                    └─┘        
par      └─┘                                    └─┘        
pid                                            └─┘        
st   ───┘└──────────────────────────────────────────────────────
169        roption.mem_some_iff.2 $ by rw e; refl),
id         └──────────────────┘           
src  ─────┘└──────────────────┘└─┘   └──┘ └┘└──┘
typ  ─────┘└──────────────────┘└─┘   └──┘└┘└──┘
doc  ─────┘                    └─┘   └──┘ └┘└──┘
txt  ─────┘                    └─┘   └──┘ └┘└──┘
par  ─────┘                    └─┘   └──┘ └┘└──┘
pid  ─────┘                    └─┘   └──┘ └─────┘
st   ────────────────────────────────┘└─────────┘└─
170      exact ⟨refl_trans_gen.refl, e⟩ },
id              └─────────────────┘  
src      └────┘ └─────────────────┘└┘ └┘
typ      └────┘ └─────────────────┘└┘└┘
doc      └────┘                    └┘ └┘
txt      └────┘                    └┘ └┘
par      └────┘                    └┘ └┘
pid                               └┘ 
st   ──────────────────────────────────┘└┘
171    { rcases pfun.mem_fix_iff.1 h with h | ⟨_, h, h'⟩;
id              └──────────────┘   
src      └─────┘└──────────────┘└─┘ └──────────────────┘
typ      └─────┘└──────────────┘└─┘└──────────────────┘
doc      └─────┘                └─┘ └──────────────────┘
txt      └─────┘                └─┘ └──────────────────┘
par      └─────┘                └─┘ └──────────────────┘
pid                            └─┘ └──────────────────┘
st   ─────────────────────────────────────────────────────
172        rw e at h; cases roption.mem_some_iff.1 h,
id                         └──────────────────┘   
src        └─┘ └───┘  └────┘└──────────────────┘└─┘
typ        └─┘└───┘  └────┘└──────────────────┘└─┘
doc        └─┘ └───┘  └────┘                    └─┘
txt        └─┘ └───┘  └────┘                    └─┘
par        └─┘ └───┘  └────┘                    └─┘
pid           └───┘                           └─┘
st   ────────┘└───────────────────────────────────┘└─
173      cases IH a' h' (by rwa e) with h₁ h₂,
id             └┘ └┘ └┘         
src      └────┘         └──┘ └──────────┘
typ      └────┘└┘└┘└┘   └──┘└──────────┘
doc      └────┘         └──┘ └──────────┘
txt      └────┘         └──┘ └──────────┘
par      └────┘         └──┘ └──────────┘
pid                    └───┘ └─────────┘
st   ─────────────────────┘└────┘└──────────┘└─
174      exact ⟨refl_trans_gen.head e h₁, h₂⟩ }
id              └─────────────────┘  └┘  └┘
src      └────┘ └─────────────────┘   └┘  └┘
typ      └────┘ └─────────────────┘└┘└┘└┘└┘
doc      └────┘                       └┘  └┘
txt      └────┘                       └┘  └┘
par      └────┘                       └┘  └┘
pid                                  └┘  
st   ────────────────────────────────────────┘└─
175  end, λ ⟨h₁, h₂⟩, begin
id          
typ         
st   ──┘              └─────
176    refine refl_trans_gen.head_induction_on h₁ _ (λ a a' h _ IH, _),
id            └──────────────────────────────┘ └┘
src    └─────┘└──────────────────────────────┘  └─┘  └──────────────┘
typ    └─────┘└──────────────────────────────┘└┘└─┘  └──────────────┘
doc    └─────┘                                  └─┘  └──────────────┘
txt    └─────┘                                  └─┘  └──────────────┘
par    └─────┘                                  └─┘  └──────────────┘
pid                                            └─┘  └──────────────┘
st   ────────────────────────────────────────────────────────────────┘└─
177    { refine pfun.mem_fix_iff.2 (or.inl _),
id              └──────────────┘    └────┘
src      └─────┘└──────────────┘└─┘ └────┘└─┘
typ      └─────┘└──────────────┘└─┘ └────┘└─┘
doc      └─────┘                └─┘       └─┘
txt      └─────┘                └─┘       └─┘
par      └─────┘                └─┘       └─┘
pid                            └─┘       └─┘
st   ───┘└──────────────────────────────────┘└─
178      rw h₂, apply roption.mem_some },
id          └┘        └──────────────┘
src      └─┘    └────┘└──────────────┘
typ      └─┘└┘  └────┘└──────────────┘
doc      └─┘    └────┘                
txt      └─┘    └────┘                
par      └─┘    └────┘                
pid                                 
st   ────────┘└───────────────────────┘└┘
179    { refine pfun.mem_fix_iff.2 (or.inr ⟨_, _, IH⟩),
id              └──────────────┘    └────┘        └┘
src      └─────┘└──────────────┘└─┘ └────┘ └────┘  └┘
typ      └─────┘└──────────────┘└─┘ └────┘ └────┘└┘└┘
doc      └─────┘                └─┘        └────┘  └┘
txt      └─────┘                └─┘        └────┘  └┘
par      └─────┘                └─┘        └────┘  └┘
pid                            └─┘        └────┘  └┘
st   ────────────────────────────────────────────────┘└─
180      rw show f a = _, from h,
id                          
src      └─┘       └───────┘
typ      └─┘    └───────┘
doc      └─┘       └───────┘
txt      └─┘       └───────┘
par      └─┘       └───────┘
pid               └───────┘
st   ──────────────────────────┘└─
181      apply roption.mem_some }
id             └──────────────┘
src      └────┘└──────────────┘
typ      └────┘└──────────────┘
doc      └────┘                
txt      └────┘                
par      └────┘                
pid                           
st   ──────────────────────────┘└─
182  end⟩
st   ──┘
183  
184  theorem eval_maximal₁ {σ} {f : σ → option σ} {a b}
id                                     └────┘ 
src                                     └────┘
typ                                    └────┘ 
185    (h : b ∈ eval f a) (c) : ¬ reaches₁ f b c | bc :=
id            └──┘           └──────┘      └┘
src            └──┘             └──────┘
typ           └──┘           └──────┘      └┘
186  let ⟨ab, b0⟩ := mem_eval.1 h, ⟨b', h', _⟩ := trans_gen.head'_iff.1 bc in
id   └─┘             └──────┘                   └─────────────────┘
src                  └──────┘                    └─────────────────┘
typ  └─┘             └──────┘                   └─────────────────┘
187  by cases b0.symm.trans h'
id            └───────────┘ └┘
src     └────┘└───────────┘  
typ     └────┘└───────────┘└┘
doc     └────┘               
txt     └────┘               
par     └────┘               
pid                         
st     └───────────────────────
188  
src  
typ  
doc  
txt  
par  
pid  
st   
189  theorem eval_maximal {σ} {f : σ → option σ} {a b}
id                                    └────┘ 
src                                    └────┘
typ                                   └────┘ 
190    (h : b ∈ eval f a) {c} : reaches f b c ↔ c = b :=
id            └──┘          └─────┘       
src            └──┘            └─────┘          
typ           └──┘          └─────┘       
191  let ⟨ab, b0⟩ := mem_eval.1 h in
id   └─┘             └──────┘  
src                  └──────┘
typ  └─┘             └──────┘  
192  refl_trans_gen_iff_eq $ λ b' h', by cases b0.symm.trans h'
id   └───────────────────┘     └┘ └┘           └───────────┘ └┘
src  └───────────────────┘               └────┘└───────────┘  
typ  └───────────────────┘     └┘ └┘     └────┘└───────────┘└┘
doc                                      └────┘               
txt                                      └────┘               
par                                      └────┘               
pid                                                          
st                                      └───────────────────────
193  
src  
typ  
doc  
txt  
par  
pid  
st   
194  theorem reaches_eval {σ} {f : σ → option σ} {a b}
id                                    └────┘ 
src                                    └────┘
typ                                   └────┘ 
195    (ab : reaches f a b) : eval f a = eval f b :=
id           └─────┘       └──┘    └──┘  
src          └─────┘          └──┘      └──┘
typ          └─────┘       └──┘    └──┘  
196  roption.ext $ λ c,
id   └─────────┘     
src  └─────────┘
typ  └─────────┘     
doc  └─────────┘
197   ⟨λ h, let ⟨ac, c0⟩ := mem_eval.1 h in
id         └─┘  └┘  └┘     └──────┘  
src                         └──────┘
typ        └─┘  └┘  └┘     └──────┘  
198      mem_eval.2 ⟨(or_iff_left_of_imp $ by exact
id       └──────┘    └────────────────┘
src      └──────┘    └────────────────┘      └─────
typ      └──────┘    └────────────────┘      └─────
doc                                           └─────
txt                                           └─────
par                                           └─────
pid                                                
st                                           └──────
199        λ cb, (eval_maximal h).1 cb ▸ refl_trans_gen.refl).1
id                └──────────┘         └─────────────────┘ 
src  ─────┘ └───┘ └──────────┘ └──┘  └─────────────────┘ 
typ  ─────┘ └───┘ └──────────┘└──┘  └─────────────────┘ 
doc  ─────┘ └───┘              └──┘   
txt  ─────┘ └───┘              └──┘   
par  ─────┘ └───┘              └──┘   
pid  ─────┘ └───┘              └──┘   
st   ──────────────────────────────────────────────────────┘
200        (reaches_total ab ac), c0⟩,
id          └───────────┘ └┘
src         └───────────┘
typ         └───────────┘ └┘
201    λ h, let ⟨bc, c0⟩ := mem_eval.1 h in mem_eval.2 ⟨ab.trans bc, c0⟩,⟩
id         └─┘  └┘  └┘     └──────┘      └──────┘   └┘└────┘
src                         └──────┘       └──────┘     └────┘
typ        └─┘  └┘  └┘     └──────┘      └──────┘   └┘└────┘
202  
203  def respects {σ₁ σ₂}
204    (f₁ : σ₁ → option σ₁) (f₂ : σ₂ → option σ₂) (tr : σ₁ → σ₂ → Prop) :=
id           └┘   └────┘ └┘        └┘   └────┘ └┘        └┘   └┘
src               └────┘                └────┘
typ          └┘   └────┘ └┘        └┘   └────┘ └┘        └┘   └┘
205  ∀ ⦃a₁ a₂⦄, tr a₁ a₂ → (match f₁ a₁ with
id      └┘ └┘   └┘ └┘ └┘          └┘ └┘
typ     └┘ └┘   └┘ └┘ └┘          └┘ └┘
206    | some b₁ := ∃ b₂, tr b₁ b₂ ∧ reaches₁ f₂ a₂ b₂
id       └──┘ └┘     └┘ └┘    └┘  └──────┘ └┘ └┘ └┘
src      └──┘                     └──────┘
typ      └──┘ └┘     └┘ └┘    └┘  └──────┘ └┘ └┘ └┘
207    | none := f₂ a₂ = none
id       └──┘    └┘ └┘  └──┘
src      └──┘           └──┘
typ      └──┘    └┘ └┘  └──┘
208    end : Prop)
209  
210  theorem tr_reaches₁ {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop}
id                                           └┘   └┘
typ                                          └┘   └┘
211    (H : respects f₁ f₂ tr) {a₁ a₂} (aa : tr a₁ a₂) {b₁} (ab : reaches₁ f₁ a₁ b₁) :
id          └──────┘ └┘ └┘ └┘                └┘ └┘ └┘             └──────┘ └┘ └┘ └┘
src         └──────┘                                              └──────┘
typ         └──────┘ └┘ └┘ └┘                └┘ └┘ └┘             └──────┘ └┘ └┘ └┘
212    ∃ b₂, tr b₁ b₂ ∧ reaches₁ f₂ a₂ b₂ :=
id      └┘ └┘ └┘ └┘  └──────┘ └┘ └┘ └┘
src                  └──────┘
typ     └┘ └┘ └┘ └┘  └──────┘ └┘ └┘ └┘
213  begin
st   └─────
214    induction ab with c₁ ac c₁ d₁ ac cd IH,
id               └┘
src    └────────┘  └────────────────────────┘
typ    └────────┘└┘└────────────────────────┘
doc    └────────┘  └────────────────────────┘
txt    └────────┘  └────────────────────────┘
par    └────────┘  └────────────────────────┘
pid               └───────────────────────┘
st   ───────────────────────────────────────┘└─
215    { have := H aa,
id                └┘
src      └──────┘ 
typ      └──────┘└┘
doc      └──────┘ 
txt      └──────┘ 
par      └──────┘ 
pid      └───┘└─┘ 
st   ───┘└──────────┘└─
216      rwa (show f₁ a₁ = _, from ac) at this },
id                 └┘ └┘          └┘
src      └──┘         └───────┘  └────────┘
typ      └──┘     └┘└┘└───────┘└┘└────────┘
doc      └──┘          └───────┘  └────────┘
txt      └──┘          └───────┘  └────────┘
par      └──┘          └───────┘  └────────┘
pid                   └───────┘  └──────┘
st   ─────────────────────────────────────────┘└┘
217    { rcases IH with ⟨c₂, cc, ac₂⟩,
id              └┘
src      └─────┘  └─────────────────┘
typ      └─────┘└┘└─────────────────┘
doc      └─────┘  └─────────────────┘
txt      └─────┘  └─────────────────┘
par      └─────┘  └─────────────────┘
pid              └─────────────────┘
st   ───────────────────────────────┘└─
218      have := H cc,
id                └┘
src      └──────┘ 
typ      └──────┘└┘
doc      └──────┘ 
txt      └──────┘ 
par      └──────┘ 
pid      └───┘└─┘ 
st   ───────────────┘└─
219      rw (show f₁ c₁ = _, from cd) at this,
id                └┘ └┘          └┘
src      └─┘          └───────┘  └───────┘
typ      └─┘     └┘└┘└───────┘└┘└───────┘
doc      └─┘          └───────┘  └───────┘
txt      └─┘          └───────┘  └───────┘
par      └─┘          └───────┘  └───────┘
pid                  └───────┘  └──────┘
st   ───────────────────────────────────────┘└─
220      rcases this with ⟨d₂, dd, cd₂⟩,
id              └──┘
src      └─────┘    └─────────────────┘
typ      └─────┘└──┘└─────────────────┘
doc      └─────┘    └─────────────────┘
txt      └─────┘    └─────────────────┘
par      └─────┘    └─────────────────┘
pid                └─────────────────┘
st   ─────────────────────────────────┘└─
221      exact ⟨_, dd, ac₂.trans cd₂⟩ }
id                 └┘  └───────┘ └─┘
src      └────┘ └─┘  └┘└───────┘   └┘
typ      └────┘ └─┘└┘└┘└───────┘└─┘└┘
doc      └────┘ └─┘  └┘            └┘
txt      └────┘ └─┘  └┘            └┘
par      └────┘ └─┘  └┘            └┘
pid            └─┘  └┘            
st   ────────────────────────────────┘└─
222  end
st   ──┘
223  
224  theorem tr_reaches {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop}
id                                          └┘   └┘
typ                                         └┘   └┘
225    (H : respects f₁ f₂ tr) {a₁ a₂} (aa : tr a₁ a₂) {b₁} (ab : reaches f₁ a₁ b₁) :
id          └──────┘ └┘ └┘ └┘                └┘ └┘ └┘             └─────┘ └┘ └┘ └┘
src         └──────┘                                              └─────┘
typ         └──────┘ └┘ └┘ └┘                └┘ └┘ └┘             └─────┘ └┘ └┘ └┘
226    ∃ b₂, tr b₁ b₂ ∧ reaches f₂ a₂ b₂ :=
id      └┘ └┘ └┘ └┘  └─────┘ └┘ └┘ └┘
src                  └─────┘
typ     └┘ └┘ └┘ └┘  └─────┘ └┘ └┘ └┘
227  begin
st   └─────
228    rcases refl_trans_gen_iff_eq_or_trans_gen.1 ab with rfl | ab,
id            └────────────────────────────────┘   └┘
src    └─────┘└────────────────────────────────┘└─┘  └────────────┘
typ    └─────┘└────────────────────────────────┘└─┘└┘└────────────┘
doc    └─────┘                                  └─┘  └────────────┘
txt    └─────┘                                  └─┘  └────────────┘
par    └─────┘                                  └─┘  └────────────┘
pid                                            └─┘  └────────────┘
st   ─────────────────────────────────────────────────────────────┘└─
229    { exact ⟨_, aa, refl_trans_gen.refl⟩ },
id                 └┘  └─────────────────┘
src      └────┘ └─┘  └┘└─────────────────┘└┘
typ      └────┘ └─┘└┘└┘└─────────────────┘└┘
doc      └────┘ └─┘  └┘                   └┘
txt      └────┘ └─┘  └┘                   └┘
par      └────┘ └─┘  └┘                   └┘
pid            └─┘  └┘                   
st   ───┘└─────────────────────────────────┘└┘
230    { exact let ⟨b₂, bb, h⟩ := tr_reaches₁ H aa ab in
id                  └┘  └┘       └─────────┘  └┘ └┘
src      └────┘      └┘  └┘ └───┘└─────────┘     └───
typ      └────┘    └┘└┘└┘└┘└───┘└─────────┘└┘└┘└───
doc      └────┘      └┘  └┘ └───┘                └───
txt      └────┘      └┘  └┘ └───┘                └───
par      └────┘      └┘  └┘ └───┘                └───
pid                 └┘  └┘ └───┘                └───
st   ────────────────────────────────────────────────────
231      ⟨b₂, bb, h.to_refl⟩ }
id                 └──────┘
src  ───┘   └┘  └┘ └──────┘└┘
typ  ───┘   └┘  └┘ └──────┘└┘
doc  ───┘   └┘  └┘         └┘
txt  ───┘   └┘  └┘         └┘
par  ───┘   └┘  └┘         └┘
pid  ───┘   └┘  └┘         
st   ───────────────────────┘└─
232  end
st   ──┘
233  
234  theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop}
id                                              └┘   └┘
typ                                             └┘   └┘
235    (H : respects f₁ f₂ tr) {a₁ a₂} (aa : tr a₁ a₂) {b₂} (ab : reaches f₂ a₂ b₂) :
id          └──────┘ └┘ └┘ └┘                └┘ └┘ └┘             └─────┘ └┘ └┘ └┘
src         └──────┘                                              └─────┘
typ         └──────┘ └┘ └┘ └┘                └┘ └┘ └┘             └─────┘ └┘ └┘ └┘
236    ∃ c₁ c₂, reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ reaches f₁ a₁ c₁ :=
id      └┘ └┘ └─────┘ └┘ └┘ └┘  └┘ └┘ └┘  └─────┘ └┘ └┘ └┘
src           └─────┘                     └─────┘
typ     └┘ └┘ └─────┘ └┘ └┘ └┘  └┘ └┘ └┘  └─────┘ └┘ └┘ └┘
237  begin
st   └─────
238    induction ab with c₂ d₂ ac cd IH,
id               └┘
src    └────────┘  └──────────────────┘
typ    └────────┘└┘└──────────────────┘
doc    └────────┘  └──────────────────┘
txt    └────────┘  └──────────────────┘
par    └────────┘  └──────────────────┘
pid               └─────────────────┘
st   ─────────────────────────────────┘└─
239    { exact ⟨_, _, refl_trans_gen.refl, aa, refl_trans_gen.refl⟩ },
id                                         └┘  └─────────────────┘
src      └────┘ └────┘                   └┘  └┘└─────────────────┘└┘
typ      └────┘ └────┘                   └┘└┘└┘└─────────────────┘└┘
doc      └────┘ └────┘                   └┘  └┘                   └┘
txt      └────┘ └────┘                   └┘  └┘                   └┘
par      └────┘ └────┘                   └┘  └┘                   └┘
pid            └────┘                   └┘  └┘                   
st   ───┘└─────────────────────────────────────────────────────────┘└┘
240    { rcases IH with ⟨e₁, e₂, ce, ee, ae⟩,
id              └┘
src      └─────┘  └────────────────────────┘
typ      └─────┘└┘└────────────────────────┘
doc      └─────┘  └────────────────────────┘
txt      └─────┘  └────────────────────────┘
par      └─────┘  └────────────────────────┘
pid              └────────────────────────┘
st   ──────────────────────────────────────┘└─
241      rcases refl_trans_gen.cases_head ce with rfl | ⟨d', cd', de⟩,
id              └───────────────────────┘ └┘
src      └─────┘└───────────────────────┘  └───────────────────────┘
typ      └─────┘└───────────────────────┘└┘└───────────────────────┘
doc      └─────┘                           └───────────────────────┘
txt      └─────┘                           └───────────────────────┘
par      └─────┘                           └───────────────────────┘
pid                                       └───────────────────────┘
st   ───────────────────────────────────────────────────────────────┘└─
242      { have := H ee, revert this,
id                  └┘
src        └──────┘     └─────────┘
typ        └──────┘└┘  └─────────┘
doc        └──────┘     └─────────┘
txt        └──────┘     └─────────┘
par        └──────┘     └─────────┘
pid        └───┘└─┘           └───┘
st   ─────┘└──────────┘└───────────┘└─
243        cases eg : f₁ e₁ with g₁; simp [respects],
id                    └┘ └┘                └──────┘
src        └────┘  └─┘    └──────┘  └────┘└──────┘
typ        └────┘  └─┘└┘└┘└──────┘  └────┘└──────┘
doc        └────┘  └─┘    └──────┘  └────┘        
txt        └────┘  └─┘    └──────┘  └────┘        
par        └────┘  └─┘    └──────┘  └────┘        
pid               └─┘    └──────┘              
st   ──────────────────────────────────────────────┘└─
244        { intro c0, cases cd.symm.trans c0 },
id                           └───────────┘ └┘
src          └──────┘  └────┘└───────────┘  
typ          └──────┘  └────┘└───────────┘└┘
doc          └──────┘  └────┘               
txt          └──────┘  └────┘               
par          └──────┘  └────┘               
pid               └─┘                      
st   ───────┘└──────┘└───────────────────────┘└┘
245        { intros g₂ gg cg,
src          └─────────────┘
typ          └─────────────┘
doc          └─────────────┘
txt          └─────────────┘
par          └─────────────┘
pid                └───────┘
st   ──────────────────────┘└─
246          rcases trans_gen.head'_iff.1 cg with ⟨d', cd', dg⟩,
id                  └─────────────────┘   └┘
src          └─────┘└─────────────────┘└─┘  └─────────────────┘
typ          └─────┘└─────────────────┘└─┘└┘└─────────────────┘
doc          └─────┘                   └─┘  └─────────────────┘
txt          └─────┘                   └─┘  └─────────────────┘
par          └─────┘                   └─┘  └─────────────────┘
pid                                   └─┘  └─────────────────┘
st   ─────────────────────────────────────────────────────────┘└─
247          cases option.mem_unique cd cd',
id                 └───────────────┘ └┘ └─┘
src          └────┘└───────────────┘  
typ          └────┘└───────────────┘└┘└─┘
doc          └────┘                   
txt          └────┘                   
par          └────┘                   
pid                                  
st   ─────────────────────────────────────┘└─
248          exact ⟨_, _, dg, gg, ae.tail eg⟩ } },
id                        └┘  └┘  └─────┘ └┘
src          └────┘ └────┘  └┘  └┘└─────┘  └┘
typ          └────┘ └────┘└┘└┘└┘└┘└─────┘└┘└┘
doc          └────┘ └────┘  └┘  └┘         └┘
txt          └────┘ └────┘  └┘  └┘         └┘
par          └────┘ └────┘  └┘  └┘         └┘
pid                └────┘  └┘  └┘         
st   ────────────────────────────────────────┘└──┘
249      { cases option.mem_unique cd cd',
id               └───────────────┘ └┘ └─┘
src        └────┘└───────────────┘  
typ        └────┘└───────────────┘└┘└─┘
doc        └────┘                   
txt        └────┘                   
par        └────┘                   
pid                                
st   ───────────────────────────────────┘└─
250        exact ⟨_, _, de, ee, ae⟩ } }
id                      └┘  └┘  └┘
src        └────┘ └────┘  └┘  └┘  └┘
typ        └────┘ └────┘└┘└┘└┘└┘└┘└┘
doc        └────┘ └────┘  └┘  └┘  └┘
txt        └────┘ └────┘  └┘  └┘  └┘
par        └────┘ └────┘  └┘  └┘  └┘
pid              └────┘  └┘  └┘  
st   ──────────────────────────────┘└───
251  end
st   ──┘
252  
253  theorem tr_eval {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop}
id                                       └┘   └┘
typ                                      └┘   └┘
254    (H : respects f₁ f₂ tr) {a₁ b₁ a₂} (aa : tr a₁ a₂)
id          └──────┘ └┘ └┘ └┘                   └┘ └┘ └┘
src         └──────┘
typ         └──────┘ └┘ └┘ └┘                   └┘ └┘ └┘
255    (ab : b₁ ∈ eval f₁ a₁) : ∃ b₂, tr b₁ b₂ ∧ b₂ ∈ eval f₂ a₂ :=
id           └┘  └──┘ └┘ └┘     └┘ └┘ └┘ └┘  └┘  └──┘ └┘ └┘
src              └──┘                            └──┘
typ          └┘  └──┘ └┘ └┘     └┘ └┘ └┘ └┘  └┘  └──┘ └┘ └┘
256  begin
st   └─────
257    cases mem_eval.1 ab with ab b0,
id           └──────┘   └┘
src    └────┘└──────┘└─┘  └─────────┘
typ    └────┘└──────┘└─┘└┘└─────────┘
doc    └────┘        └─┘  └─────────┘
txt    └────┘        └─┘  └─────────┘
par    └────┘        └─┘  └─────────┘
pid                 └─┘  └─────────┘
st   ───────────────────────────────┘└─
258    rcases tr_reaches H aa ab with ⟨b₂, bb, ab⟩,
id            └────────┘  └┘ └┘
src    └─────┘└────────┘     └────────────────┘
typ    └─────┘└────────┘└┘└┘└────────────────┘
doc    └─────┘               └────────────────┘
txt    └─────┘               └────────────────┘
par    └─────┘               └────────────────┘
pid                         └────────────────┘
st   ────────────────────────────────────────────┘└─
259    refine ⟨_, bb, mem_eval.2 ⟨ab, _⟩⟩,
id                └┘  └──────┘    └┘
src    └─────┘ └─┘  └┘└──────┘└─┘   └───┘
typ    └─────┘ └─┘└┘└┘└──────┘└─┘ └┘└───┘
doc    └─────┘ └─┘  └┘        └─┘   └───┘
txt    └─────┘ └─┘  └┘        └─┘   └───┘
par    └─────┘ └─┘  └┘        └─┘   └───┘
pid           └─┘  └┘        └─┘   └───┘
st   ───────────────────────────────────┘└─
260    have := H bb, rwa b0 at this
id              └┘      └┘
src    └──────┘     └──┘  └───────┘
typ    └──────┘└┘  └──┘└┘└───────┘
doc    └──────┘     └──┘  └───────┘
txt    └──────┘     └──┘  └───────┘
par    └──────┘     └──┘  └───────┘
pid    └───┘└─┘          └──────┘
st   ─────────────┘└───────────────┘
261  end
st   └─┘
262  
263  theorem tr_eval_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop}
id                                           └┘   └┘
typ                                          └┘   └┘
264    (H : respects f₁ f₂ tr) {a₁ b₂ a₂} (aa : tr a₁ a₂)
id          └──────┘ └┘ └┘ └┘                   └┘ └┘ └┘
src         └──────┘
typ         └──────┘ └┘ └┘ └┘                   └┘ └┘ └┘
265    (ab : b₂ ∈ eval f₂ a₂) : ∃ b₁, tr b₁ b₂ ∧ b₁ ∈ eval f₁ a₁ :=
id           └┘  └──┘ └┘ └┘     └┘ └┘ └┘ └┘  └┘  └──┘ └┘ └┘
src              └──┘                            └──┘
typ          └┘  └──┘ └┘ └┘     └┘ └┘ └┘ └┘  └┘  └──┘ └┘ └┘
266  begin
st   └─────
267    cases mem_eval.1 ab with ab b0,
id           └──────┘   └┘
src    └────┘└──────┘└─┘  └─────────┘
typ    └────┘└──────┘└─┘└┘└─────────┘
doc    └────┘        └─┘  └─────────┘
txt    └────┘        └─┘  └─────────┘
par    └────┘        └─┘  └─────────┘
pid                 └─┘  └─────────┘
st   ───────────────────────────────┘└─
268    rcases tr_reaches_rev H aa ab with ⟨c₁, c₂, bc, cc, ac⟩,
id            └────────────┘  └┘ └┘
src    └─────┘└────────────┘     └────────────────────────┘
typ    └─────┘└────────────┘└┘└┘└────────────────────────┘
doc    └─────┘                   └────────────────────────┘
txt    └─────┘                   └────────────────────────┘
par    └─────┘                   └────────────────────────┘
pid                             └────────────────────────┘
st   ────────────────────────────────────────────────────────┘└─
269    cases (refl_trans_gen_iff_eq
id            └───────────────────┘
src    └────┘ └───────────────────┘
typ    └────┘ └───────────────────┘
doc    └────┘                      
txt    └────┘                      
par    └────┘                      
pid                               
st   ───────────────────────────────
270      (by exact option.eq_none_iff_forall_not_mem.1 b0)).1 bc,
id                 └───────────────────────────────┘   └┘     └┘
src  ───┘   └────┘└───────────────────────────────┘└─┘  └───┘
typ  ───┘   └────┘└───────────────────────────────┘└─┘└┘└───┘└┘
doc  ───┘   └────┘                                 └─┘  └───┘
txt  ───┘   └────┘                                 └─┘  └───┘
par  ───┘   └────┘                                 └─┘  └───┘
pid  ───┘   └─────┘                                 └─┘  └───┘
st   ──────┘└───────────────────────────────────────────┘└─────┘└─
271    refine ⟨_, cc, mem_eval.2 ⟨ac, _⟩⟩,
id                └┘  └──────┘    └┘
src    └─────┘ └─┘  └┘└──────┘└─┘   └───┘
typ    └─────┘ └─┘└┘└┘└──────┘└─┘ └┘└───┘
doc    └─────┘ └─┘  └┘        └─┘   └───┘
txt    └─────┘ └─┘  └┘        └─┘   └───┘
par    └─────┘ └─┘  └┘        └─┘   └───┘
pid           └─┘  └┘        └─┘   └───┘
st   ───────────────────────────────────┘└─
272    have := H cc, cases f₁ c₁ with d₁, {refl},
id              └┘        └┘ └┘
src    └──────┘     └────┘    └──────┘   └──┘
typ    └──────┘└┘  └────┘└┘└┘└──────┘   └──┘
doc    └──────┘     └────┘    └──────┘   └──┘
txt    └──────┘     └────┘    └──────┘   └──┘
par    └──────┘     └────┘    └──────┘   └──┘
pid    └───┘└─┘              └──────┘
st   ─────────────┘└───────────────────┘└─────┘└┘
273    rcases this with ⟨d₂, dd, bd⟩,
id            └──┘
src    └─────┘    └────────────────┘
typ    └─────┘└──┘└────────────────┘
doc    └─────┘    └────────────────┘
txt    └─────┘    └────────────────┘
par    └─────┘    └────────────────┘
pid              └────────────────┘
st   ──────────────────────────────┘└─
274    rcases trans_gen.head'_iff.1 bd with ⟨e, h, _⟩,
id            └─────────────────┘   └┘
src    └─────┘└─────────────────┘└─┘  └─────────────┘
typ    └─────┘└─────────────────┘└─┘└┘└─────────────┘
doc    └─────┘                   └─┘  └─────────────┘
txt    └─────┘                   └─┘  └─────────────┘
par    └─────┘                   └─┘  └─────────────┘
pid                             └─┘  └─────────────┘
st   ───────────────────────────────────────────────┘└─
275    cases b0.symm.trans h
id           └───────────┘ 
src    └────┘└───────────┘ 
typ    └────┘└───────────┘
doc    └────┘              
txt    └────┘              
par    └────┘              
pid                       
st   ───────────────────────┘
276  end
st   └─┘
277  
278  theorem tr_eval_dom {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop}
id                                           └┘   └┘
typ                                          └┘   └┘
279    (H : respects f₁ f₂ tr) {a₁ a₂} (aa : tr a₁ a₂) :
id          └──────┘ └┘ └┘ └┘                └┘ └┘ └┘
src         └──────┘
typ         └──────┘ └┘ └┘ └┘                └┘ └┘ └┘
280    (eval f₂ a₂).dom ↔ (eval f₁ a₁).dom :=
id      └──┘ └┘ └┘ └─┘    └──┘ └┘ └┘ └─┘
src     └──┘       └─┘    └──┘       └─┘
typ     └──┘ └┘ └┘ └─┘    └──┘ └┘ └┘ └─┘
281  ⟨λ h, let ⟨b₂, tr, h, _⟩ := tr_eval_rev H aa ⟨h, rfl⟩ in h,
id        └─┘                  └─────────┘  └┘    └─┘
src                              └─────────┘          └─┘
typ       └─┘                  └─────────┘  └┘    └─┘
282   λ h, let ⟨b₂, tr, h, _⟩ := tr_eval H aa ⟨h, rfl⟩ in h⟩
id        └─┘                  └─────┘  └┘    └─┘
src                              └─────┘          └─┘
typ       └─┘                  └─────┘  └┘    └─┘
283  
284  def frespects {σ₁ σ₂} (f₂ : σ₂ → option σ₂) (tr : σ₁ → σ₂) (a₂ : σ₂) : option σ₁ → Prop
id                               └┘   └────┘ └┘        └┘   └┘        └┘    └────┘ └┘ 
src                                   └────┘                                └────┘
typ                              └┘   └────┘ └┘        └┘   └┘        └┘    └────┘ └┘ 
285  | (some b₁) := reaches₁ f₂ a₂ (tr b₁)
id      └──┘ └┘     └──────┘ └┘ └┘  └┘
src     └──┘        └──────┘
typ     └──┘ └┘     └──────┘ └┘ └┘  └┘
286  | none := f₂ a₂ = none
id     └──┘    └┘ └┘  └──┘
src    └──┘           └──┘
typ    └──┘    └┘ └┘  └──┘
287  
288  theorem frespects_eq {σ₁ σ₂} {f₂ : σ₂ → option σ₂} {tr : σ₁ → σ₂} {a₂ b₂}
id                                      └┘   └────┘ └┘        └┘   └┘
src                                          └────┘
typ                                     └┘   └────┘ └┘        └┘   └┘
289    (h : f₂ a₂ = f₂ b₂) : ∀ {b₁}, frespects f₂ tr a₂ b₁ ↔ frespects f₂ tr b₂ b₁
id          └┘ └┘  └┘ └┘      └┘   └───────┘ └┘ └┘ └┘ └┘  └───────┘ └┘ └┘ └┘ └┘
src                                 └───────┘              └───────┘
typ         └┘ └┘  └┘ └┘      └┘   └───────┘ └┘ └┘ └┘ └┘  └───────┘ └┘ └┘ └┘ └┘
290  | (some b₁) := reaches₁_eq h
id      └──┘        └─────────┘ 
src     └──┘        └─────────┘
typ     └──┘        └─────────┘ 
291  | none := by unfold frespects; rw h
id     └──┘                            
src    └──┘       └──────────────┘  └─┘ 
typ    └──┘       └──────────────┘  └─┘
doc               └──────────────┘  └─┘ 
txt               └──────────────┘  └─┘ 
par               └──────────────┘  └─┘ 
pid                     └────────┘     
st               └────────────────────┘
292  
src  
typ  
doc  
txt  
par  
pid  
st   
293  theorem fun_respects {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂} :
id                                            └┘   └┘
typ                                           └┘   └┘
294    respects f₁ f₂ (λ a b, tr a = b) ↔ ∀ ⦃a₁⦄, frespects f₂ tr (tr a₁) (f₁ a₁) :=
id     └──────┘ └┘ └┘       └┘         └┘   └───────┘ └┘ └┘  └┘ └┘   └┘ └┘
src    └──────┘                                 └───────┘
typ    └──────┘ └┘ └┘       └┘         └┘   └───────┘ └┘ └┘  └┘ └┘   └┘ └┘
295  forall_congr $ λ a₁, by cases f₁ a₁; simp only [frespects, respects, exists_eq_left', forall_eq']
id   └──────────┘     └┘           └┘ └┘             └───────┘  └──────┘  └─────────────┘  └────────┘
src  └──────────┘            └────┘      └─────────┘└───────┘└┘└──────┘└┘└─────────────┘└┘└────────┘└─
typ  └──────────┘     └┘     └────┘└┘└┘  └─────────┘└───────┘└┘└──────┘└┘└─────────────┘└┘└────────┘└─
doc                          └────┘      └─────────┘         └┘        └┘               └┘          └─
txt                          └────┘      └─────────┘         └┘        └┘               └┘          └─
par                          └────┘      └─────────┘         └┘        └┘               └┘          └─
pid                                         └──┘└┘         └┘        └┘               └┘          
st                          └──────────────────────────────────────────────────────────────────────────
296  
src  
typ  
doc  
txt  
par  
pid  
st   
297  theorem tr_eval' {σ₁ σ₂}
298    (f₁ : σ₁ → option σ₁) (f₂ : σ₂ → option σ₂) (tr : σ₁ → σ₂)
id           └┘   └────┘ └┘        └┘   └────┘ └┘        └┘   └┘
src               └────┘                └────┘
typ          └┘   └────┘ └┘        └┘   └────┘ └┘        └┘   └┘
299    (H : respects f₁ f₂ (λ a b, tr a = b))
id          └──────┘ └┘ └┘       └┘   
src         └──────┘                    
typ         └──────┘ └┘ └┘       └┘   
300    (a₁) : eval f₂ (tr a₁) = tr <$> eval f₁ a₁ :=
id            └──┘ └┘  └┘ └┘   └┘ └─┘ └──┘ └┘ └┘
src           └──┘                └─┘ └──┘
typ           └──┘ └┘  └┘ └┘   └┘ └─┘ └──┘ └┘ └┘
301  roption.ext $ λ b₂,
id   └─────────┘     └┘
src  └─────────┘
typ  └─────────┘     └┘
doc  └─────────┘
302   ⟨λ h, let ⟨b₁, bb, hb⟩ := tr_eval_rev H rfl h in
id         └─┘  └┘  └┘  └┘     └─────────┘  └─┘ 
src                             └─────────┘   └─┘
typ        └─┘  └┘  └┘  └┘     └─────────┘  └─┘ 
303      (roption.mem_map_iff _).2 ⟨b₁, hb, bb⟩,
id        └─────────────────┘   
src       └─────────────────┘   
typ       └─────────────────┘   
304    λ h, begin
id       
typ      
st          └─────
305      rcases (roption.mem_map_iff _).1 h with ⟨b₁, ab, bb⟩,
id               └─────────────────┘      
src      └─────┘ └─────────────────┘└────┘ └────────────────┘
typ      └─────┘ └─────────────────┘└────┘└────────────────┘
doc      └─────┘                    └────┘ └────────────────┘
txt      └─────┘                    └────┘ └────────────────┘
par      └─────┘                    └────┘ └────────────────┘
pid                                └────┘ └────────────────┘
st   ───────────────────────────────────────────────────────┘└─
306      rcases tr_eval H rfl ab with ⟨_, rfl, h⟩,
id              └─────┘  └─┘ └┘
src      └─────┘└─────┘ └─┘  └───────────────┘
typ      └─────┘└─────┘└─┘└┘└───────────────┘
doc      └─────┘             └───────────────┘
txt      └─────┘             └───────────────┘
par      └─────┘             └───────────────┘
pid                         └───────────────┘
st   ───────────────────────────────────────────┘└─
307      rwa bb at h
id           └┘
src      └──┘  └─────
typ      └──┘└┘└─────
doc      └──┘  └─────
txt      └──┘  └─────
par      └──┘  └─────
pid           └───┘
st   ────────────────
308    end⟩
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
309  
310  def dwrite {K} [decidable_eq K] {C : K → Type*}
id                   └──────────┘        
src                  └──────────┘
typ                  └──────────┘        
311    (S : ∀ k, C k) (k') (l : C k') (k) : C k :=
id                            └┘         
typ                           └┘         
312  if h : k = k' then eq.rec_on h.symm l else S k
id   └┘       └┘      └───────┘ └───┘        
src  └┘                └───────┘  └───┘        
typ  └┘       └┘      └───────┘ └───┘        
313  
314  @[simp] theorem dwrite_eq {K} [decidable_eq K] {C : K → Type*}
id                                  └──────────┘        
src                                 └──────────┘
typ                                 └──────────┘        
doc    └──┘
315    (S : ∀ k, C k) (k) (l : C k) : dwrite S k l k = l :=
id                               └────┘      
src                                   └────┘         
typ                              └────┘      
316  dif_pos rfl
id   └─────┘ └─┘
src  └─────┘ └─┘
typ  └─────┘ └─┘
317  
318  @[simp] theorem dwrite_ne {K} [decidable_eq K] {C : K → Type*}
id                                  └──────────┘        
src                                 └──────────┘
typ                                 └──────────┘        
doc    └──┘
319    (S : ∀ k, C k) (k') (l : C k') (k) (h : ¬ k = k') : dwrite S k' l k = S k :=
id                            └┘              └┘    └────┘  └┘     
src                                                      └────┘          
typ                           └┘              └┘    └────┘  └┘     
320  dif_neg h
id   └─────┘ 
src  └─────┘
typ  └─────┘ 
321  
322  @[simp] theorem dwrite_self
doc    └──┘
323    {K} [decidable_eq K] {C : K → Type*}
id          └──────────┘        
src         └──────────┘
typ         └──────────┘        
324    (S : ∀ k, C k) (k) : dwrite S k (S k) = S :=
id                       └────┘        
src                         └────┘           
typ                      └────┘        
325  funext $ λ k', by unfold dwrite; split_ifs; [subst h, refl]
id   └────┘     └┘                                     
src  └────┘            └───────────┘  └───────┘  └────┘   └──┘
typ  └────┘     └┘     └───────────┘  └───────┘  └────┘  └──┘
doc                    └───────────┘  └───────┘   └────┘   └──┘
txt                    └───────────┘  └───────┘   └────┘   └──┘
par                    └───────────┘  └───────┘   └────┘   └──┘
pid                          └─────┘                   
st                    └────────────────────────────────────────┘
326  
327  namespace TM0
328  
329  section
330  parameters (Γ : Type*) [inhabited Γ] -- type of tape symbols
id                   └───┘   └───────┘
src                          └───────┘
typ                  └───┘   └───────┘
331  parameters (Λ : Type*) [inhabited Λ] -- type of "labels" or TM states
id                   └───┘   └───────┘
src                          └───────┘
typ                  └───┘   └───────┘
332  
333  /-- A Turing machine "statement" is just a command to either move
334    left or right, or write a symbol on the tape. -/
335  @[derive inhabited]
id            └───────┘
src           └───────┘
typ           └───────┘
doc    └────┘
336  inductive stmt
337  | move {} : dir → stmt
id               └─┘
src              └─┘
typ              └─┘
doc              └─┘
338  | write {} : Γ → stmt
339  
340  /-- A Post-Turing machine with symbol type `Γ` and label type `Λ`
341    is a function which, given the current state `q : Λ` and
342    the tape head `a : Γ`, either halts (returns `none`) or returns
343    a new state `q' : Λ` and a `stmt` describing what to do,
344    either a move left or right, or a write command.
345  
346    Both `Λ` and `Γ` are required to be inhabited; the default value
347    for `Γ` is the "blank" tape value, and the default value of `Λ` is
348    the initial state. -/
349  def machine := Λ → Γ → option (Λ × stmt)
id                        └────┘    └──┘
src                         └────┘     └──┘
typ                       └────┘    └──┘
doc                                     └──┘
350  
351  instance machine.inhabited : inhabited machine := by unfold machine; apply_instance
id                                └───────┘ └─────┘
src                               └───────┘ └─────┘       └────────────┘  └──────────────
typ                               └───────┘ └─────┘       └────────────┘  └──────────────
doc                                         └─────┘       └────────────┘  └──────────────
txt                                                       └────────────┘  └──────────────
par                                                       └────────────┘  └──────────────
pid                                                             └──────┘                
st                                                       └───────────────────────────────
352  
src  
typ  
doc  
txt  
par  
pid  
st   
353  /-- The configuration state of a Turing machine during operation
354    consists of a label (machine state), and a tape, represented in
355    the form `(a, L, R)` meaning the tape looks like `L.rev ++ [a] ++ R`
356    with the machine currently reading the `a`. The lists are
357    automatically extended with blanks as the machine moves around. -/
358  @[derive inhabited]
id            └───────┘
src           └───────┘
typ           └───────┘
doc    └────┘
359  structure cfg :=
360  (q : Λ)
id        
typ       
361  (tape : tape Γ)
id           └──┘ 
src          └──┘
typ          └──┘ 
362  
363  parameters {Γ Λ}
364  /-- Execution semantics of the Turing machine. -/
365  def step (M : machine) : cfg → option cfg
id                 └─────┘    └─┘  └────┘ └─┘
src                └─────┘    └─┘   └────┘ └─┘
typ                └─────┘    └─┘  └────┘ └─┘
doc                └─────┘    └─┘          └─┘
366  | ⟨q, T⟩ := (M q T.1).map (λ ⟨q', a⟩, ⟨q',
id                    └─┘     └┘  
src                      └─┘
typ                   └─┘     └┘  
367    match a with
368    | stmt.move d := T.move d
id       └───────┘      └───┘
src      └───────┘       └───┘
typ      └───────┘      └───┘
369    | stmt.write a := T.write a
id       └────────┘      └────┘
src      └────────┘       └────┘
typ      └────────┘      └────┘
370    end⟩)
371  
372  /-- The statement `reaches M s₁ s₂` means that `s₂` is obtained
373    starting from `s₁` after a finite number of steps from `s₂`. -/
374  def reaches (M : machine) : cfg → cfg → Prop :=
id                    └─────┘    └─┘   └─┘
src                   └─────┘    └─┘   └─┘
typ                   └─────┘    └─┘   └─┘
doc                   └─────┘    └─┘   └─┘
375  refl_trans_gen (λ a b, b ∈ step M a)
id   └────────────┘         └──┘  
src  └────────────┘            └──┘
typ  └────────────┘         └──┘  
doc  └────────────┘             └──┘
376  
377  /-- The initial configuration. -/
378  def init (l : list Γ) : cfg :=
id                 └──┘     └─┘
src                └──┘      └─┘
typ                └──┘     └─┘
doc                          └─┘
379  ⟨default Λ, tape.mk l⟩
id    └─────┘   └─────┘ 
src   └─────┘    └─────┘
typ   └─────┘   └─────┘ 
380  
381  /-- Evaluate a Turing machine on initial input to a final state,
382    if it terminates. -/
383  def eval (M : machine) (l : list Γ) : roption (list Γ) :=
id                 └─────┘       └──┘     └─────┘  └──┘ 
src                └─────┘       └──┘      └─────┘  └──┘
typ                └─────┘       └──┘     └─────┘  └──┘ 
doc                └─────┘                 └─────┘
384  (eval (step M) (init l)).map (λ c, c.tape.2.2)
id    └──┘  └──┘    └──┘   └─┘       └───┘ 
src   └──┘  └──┘     └──┘    └─┘         └───┘ 
typ   └──┘  └──┘    └──┘   └─┘       └───┘ 
doc         └──┘     └──┘    └─┘
385  
386  /-- The raw definition of a Turing machine does not require that
387    `Γ` and `Λ` are finite, and in practice we will be interested
388    in the infinite `Λ` case. We recover instead a notion of
389    "effectively finite" Turing machines, which only make use of a
390    finite subset of their states. We say that a set `S ⊆ Λ`
391    supports a Turing machine `M` if `S` is closed under the
392    transition function and contains the initial state. -/
393  def supports (M : machine) (S : set Λ) :=
id                     └─────┘       └─┘ 
src                    └─────┘       └─┘
typ                    └─────┘       └─┘ 
doc                    └─────┘
394  default Λ ∈ S ∧ ∀ {q a q' s}, (q', s) ∈ M q a → q ∈ S → q' ∈ S
id   └─────┘          └┘    └┘               └┘  
src  └─────┘                                               
typ  └─────┘          └┘    └┘               └┘  
395  
396  theorem step_supports (M : machine) {S}
id                              └─────┘
src                             └─────┘
typ                             └─────┘
doc                             └─────┘
397    (ss : supports M S) : ∀ {c c' : cfg},
id           └──────┘               └─┘
src          └──────┘                  └─┘
typ          └──────┘               └─┘
doc          └──────┘                  └─┘
398    c' ∈ step M c → c.q ∈ S → c'.q ∈ S
id     └┘  └──┘     └┘     └┘└┘  
src        └──┘        └┘        └┘ 
typ    └┘  └──┘     └┘     └┘└┘  
doc         └──┘
399  | ⟨q, T⟩ c' h₁ h₂ := begin
st                        └─────
400    rcases option.map_eq_some'.1 h₁ with ⟨⟨q', a⟩, h, rfl⟩,
id            └─────────────────┘   └┘
src    └─────┘└─────────────────┘└─┘  └─────────────────────┘
typ    └─────┘└─────────────────┘└─┘└┘└─────────────────────┘
doc    └─────┘                   └─┘  └─────────────────────┘
txt    └─────┘                   └─┘  └─────────────────────┘
par    └─────┘                   └─┘  └─────────────────────┘
pid                             └─┘  └─────────────────────┘
st   ───────────────────────────────────────────────────────┘└─
401    exact ss.2 h h₂,
id           └┘    └┘
src    └────┘  └─┘ 
typ    └────┘└┘└─┘└┘
doc    └────┘  └─┘ 
txt    └────┘  └─┘ 
par    └────┘  └─┘ 
pid           └─┘ 
st   ────────────────┘└─
402  end
st   ──┘
403  
404  theorem univ_supports (M : machine) : supports M set.univ :=
id                              └─────┘    └──────┘  └──────┘
src                             └─────┘    └──────┘   └──────┘
typ                             └─────┘    └──────┘  └──────┘
doc                             └─────┘    └──────┘
405  ⟨trivial, λ q a q' s h₁ h₂, trivial⟩
id    └─────┘      └┘  └┘ └┘  └─────┘
src   └─────┘                    └─────┘
typ   └─────┘      └┘  └┘ └┘  └─────┘
406  
407  end
408  
409  section
410  variables {Γ : Type*} [inhabited Γ]
id                         └───────┘
src                         └───────┘
typ                        └───────┘
411  variables {Γ' : Type*} [inhabited Γ']
id                           └───────┘
src                          └───────┘
typ                          └───────┘
412  variables {Λ : Type*} [inhabited Λ]
id                          └───────┘
src                         └───────┘
typ                         └───────┘
413  variables {Λ' : Type*} [inhabited Λ']
id                           └───────┘
src                          └───────┘
typ                          └───────┘
414  
415  def stmt.map (f : Γ → Γ') : stmt Γ → stmt Γ'
id                        └┘    └──┘   └──┘ └┘
src                              └──┘     └──┘
typ                       └┘    └──┘   └──┘ └┘
doc                              └──┘     └──┘
416  | (stmt.move d)  := stmt.move d
id      └───────┘       └───────┘
src     └───────┘        └───────┘
typ     └───────┘       └───────┘
417  | (stmt.write a) := stmt.write (f a)
id      └────────┘      └────────┘  
src     └────────┘       └────────┘
typ     └────────┘      └────────┘  
418  
419  def cfg.map (f : Γ → Γ') (g : Λ → Λ') : cfg Γ Λ → cfg Γ' Λ'
id                       └┘          └┘    └─┘    └─┘ └┘ └┘
src                                          └─┘       └─┘
typ                      └┘          └┘    └─┘    └─┘ └┘ └┘
doc                                          └─┘       └─┘
420  | ⟨q, T⟩ := ⟨g q, T.map f⟩
id                   └──┘ 
src                     └──┘
typ                  └──┘ 
421  
422  variables (M : machine Γ Λ)
id                  └─────┘
src                 └─────┘
typ                 └─────┘
doc                 └─────┘
423    (f₁ : Γ → Γ') (f₂ : Γ' → Γ) (g₁ : Λ → Λ') (g₂ : Λ' → Λ)
424  
425  def machine.map : machine Γ' Λ'
id                     └─────┘ └┘ └┘
src                    └─────┘
typ                    └─────┘ └┘ └┘
doc                    └─────┘
426  | q l := (M (g₂ q) (f₂ l)).map (prod.map g₁ (stmt.map f₁))
id             └┘     └┘    └─┘   └──────┘ └┘  └──────┘ └┘
src                            └─┘   └──────┘     └──────┘
typ            └┘     └┘    └─┘   └──────┘ └┘  └──────┘ └┘
427  
428  theorem machine.map_step {S} (ss : supports M S)
id                                      └──────┘  
src                                     └──────┘
typ                                     └──────┘  
doc                                     └──────┘
429    [pointed_map f₁] (f₂₁ : function.right_inverse f₁ f₂)
id      └─────────┘ └┘         └────────────────────┘ └┘ └┘
src     └─────────┘            └────────────────────┘
typ     └─────────┘ └┘         └────────────────────┘ └┘ └┘
430    (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
id                   └┘  └┘    
src                             
typ                  └┘  └┘    
431    ∀ c : cfg Γ Λ, c.q ∈ S →
id          └─┘    └┘  
src          └─┘       └┘ 
typ         └─┘    └┘  
doc          └─┘
432      (step M c).map (cfg.map f₁ g₁) =
id        └──┘   └─┘   └─────┘ └┘ └┘  
src       └──┘     └─┘   └─────┘        
typ       └──┘   └─┘   └─────┘ └┘ └┘  
doc       └──┘
433      step (M.map f₁ f₂ g₁ g₂) (cfg.map f₁ g₁ c)
id       └──┘  └──┘ └┘ └┘ └┘ └┘   └─────┘ └┘ └┘ 
src      └──┘   └──┘               └─────┘
typ      └──┘  └──┘ └┘ └┘ └┘ └┘   └─────┘ └┘ └┘ 
doc      └──┘
434  | ⟨q, T⟩ h := begin
st                 └─────
435    unfold step machine.map cfg.map,
src    └─────────────────────────────┘
typ    └─────────────────────────────┘
doc    └─────────────────────────────┘
txt    └─────────────────────────────┘
par    └─────────────────────────────┘
pid          └───────────────────────┘
st   ────────────────────────────────┘└─
436    simp only [turing.tape.map_fst, g₂₁ q h, f₂₁ _],
id                └─────────────────┘  └─┘    └─┘
src    └─────────┘└─────────────────┘└┘     └┘   └─┘
typ    └─────────┘└─────────────────┘└┘└─┘└┘└─┘└─┘
doc    └─────────┘                   └┘     └┘   └─┘
txt    └─────────┘                   └┘     └┘   └─┘
par    └─────────┘                   └┘     └┘   └─┘
pid        └──┘└┘                   └┘     └┘   └─┘
st   ────────────────────────────────────────────────┘└─
437    rcases M q T.1 with _|⟨q', d|a⟩, {refl},
id              
src    └─────┘   └─────────────────┘   └──┘
typ    └─────┘└─────────────────┘   └──┘
doc    └─────┘   └─────────────────┘   └──┘
txt    └─────┘   └─────────────────┘   └──┘
par    └─────┘   └─────────────────┘   └──┘
pid             └─────────────────┘
st   ────────────────────────────────┘└─────┘└┘
438    { simp only [step, cfg.map, option.map_some', tape.map_move f₁], refl },
id                  └──┘  └─────┘  └──────────────┘  └───────────┘ └┘
src      └─────────┘└──┘└┘└─────┘└┘└──────────────┘└┘└───────────┘    └───┘
typ      └─────────┘└──┘└┘└─────┘└┘└──────────────┘└┘└───────────┘└┘  └───┘
doc      └─────────┘└──┘└┘       └┘                └┘                 └───┘
txt      └─────────┘    └┘       └┘                └┘                 └───┘
par      └─────────┘    └┘       └┘                └┘                 └───┘
pid          └──┘└┘    └┘       └┘                └┘                     
st   ───┘└───────────────────────────────────────────────────────────┘└─────┘└┘
439    { simp only [step, cfg.map, option.map_some', tape.map_write], refl }
id                  └──┘  └─────┘  └──────────────┘  └────────────┘
src      └─────────┘└──┘└┘└─────┘└┘└──────────────┘└┘└────────────┘  └───┘
typ      └─────────┘└──┘└┘└─────┘└┘└──────────────┘└┘└────────────┘  └───┘
doc      └─────────┘└──┘└┘       └┘                └┘                └───┘
txt      └─────────┘    └┘       └┘                └┘                └───┘
par      └─────────┘    └┘       └┘                └┘                └───┘
pid          └──┘└┘    └┘       └┘                └┘                    
st   ──────────────────────────────────────────────────────────────┘└─────┘└─
440  end
st   ──┘
441  
442  theorem map_init [pointed_map f₁] [g0 : pointed_map g₁] (l : list Γ) :
id                     └─────────┘ └┘        └─────────┘ └┘       └──┘ 
src                    └─────────┘           └─────────┘          └──┘
typ                    └─────────┘ └┘        └─────────┘ └┘       └──┘ 
443    (init l).map f₁ g₁ = init (l.map f₁) :=
id      └──┘  └─┘  └┘ └┘  └──┘  └──┘ └┘
src     └──┘   └─┘         └──┘   └──┘
typ     └──┘  └─┘  └┘ └┘  └──┘  └──┘ └┘
doc     └──┘                └──┘
444  congr (congr_arg cfg.mk g0) (tape.map_mk _ _)
id   └───┘  └───────┘ └────┘ └┘   └─────────┘
src  └───┘  └───────┘ └────┘      └─────────┘
typ  └───┘  └───────┘ └────┘ └┘   └─────────┘
445  
446  theorem machine.map_respects {S} (ss : supports M S)
id                                          └──────┘  
src                                         └──────┘
typ                                         └──────┘  
doc                                         └──────┘
447    [pointed_map f₁] [pointed_map g₁]
id      └─────────┘ └┘   └─────────┘ └┘
src     └─────────┘      └─────────┘
typ     └─────────┘ └┘   └─────────┘ └┘
448    (f₂₁ : function.right_inverse f₁ f₂)
id            └────────────────────┘ └┘ └┘
src           └────────────────────┘
typ           └────────────────────┘ └┘ └┘
449    (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
id                   └┘  └┘    
src                              
typ                  └┘  └┘    
450    respects (step M) (step (M.map f₁ f₂ g₁ g₂))
id     └──────┘  └──┘    └──┘  └──┘ └┘ └┘ └┘ └┘
src    └──────┘  └──┘     └──┘   └──┘
typ    └──────┘  └──┘    └──┘  └──┘ └┘ └┘ └┘ └┘
doc              └──┘     └──┘
451      (λ a b, a.q ∈ S ∧ cfg.map f₁ g₁ a = b)
id             └┘    └─────┘ └┘ └┘   
src               └┘     └─────┘         
typ            └┘    └─────┘ └┘ └┘   
452  | c _ ⟨cs, rfl⟩ := begin
id              └─┘
src             └─┘
typ             └─┘
st                      └─────
453    cases e : step M c with c'; unfold respects,
id               └──┘  
src    └────┘ └─┘└──┘  └──────┘  └─────────────┘
typ    └────┘ └─┘└──┘└──────┘  └─────────────┘
doc    └────┘ └─┘└──┘  └──────┘  └─────────────┘
txt    └────┘ └─┘      └──────┘  └─────────────┘
par    └────┘ └─┘      └──────┘  └─────────────┘
pid          └─┘      └──────┘        └───────┘
st   ────────────────────────────────────────────┘└─
454    { rw [← M.map_step f₁ f₂ g₁ g₂ ss f₂₁ g₂₁ _ cs, e], refl },
id             └────────┘ └┘ └┘ └┘ └┘ └┘ └─┘ └─┘   └┘  
src      └────┘└────────┘                └─┘  └┘   └───┘
typ      └────┘└────────┘└┘└┘└┘└┘└┘└─┘└─┘└─┘└┘└┘  └───┘
doc      └────┘                          └─┘  └┘   └───┘
txt      └────┘                          └─┘  └┘   └───┘
par      └────┘                          └─┘  └┘   └───┘
pid        └──┘                          └─┘  └┘       
st   ───┘└──────────────────────────────────────────┘└─┘└──────┘└┘
455    { refine ⟨_, ⟨step_supports M ss e cs, rfl⟩, trans_gen.single _⟩,
id                   └───────────┘  └┘  └┘  └─┘   └──────────────┘
src      └─────┘ └─┘ └───────────┘      └┘└─┘└─┘└──────────────┘└─┘
typ      └─────┘ └─┘ └───────────┘└┘└┘└┘└─┘└─┘└──────────────┘└─┘
doc      └─────┘ └─┘                    └┘   └─┘                └─┘
txt      └─────┘ └─┘                    └┘   └─┘                └─┘
par      └─────┘ └─┘                    └┘   └─┘                └─┘
pid             └─┘                    └┘   └─┘                └─┘
st   ─────────────────────────────────────────────────────────────────┘└─
456      rw [← M.map_step f₁ f₂ g₁ g₂ ss f₂₁ g₂₁ _ cs, e], exact rfl }
id             └────────┘ └┘ └┘ └┘ └┘ └┘ └─┘ └─┘   └┘           └─┘
src      └────┘└────────┘                └─┘  └┘   └────┘└─┘
typ      └────┘└────────┘└┘└┘└┘└┘└┘└─┘└─┘└─┘└┘└┘  └────┘└─┘
doc      └────┘                          └─┘  └┘   └────┘   
txt      └────┘                          └─┘  └┘   └────┘   
par      └────┘                          └─┘  └┘   └────┘   
pid        └──┘                          └─┘  └┘           
st   ───────────────────────────────────────────────┘└─┘└───────────┘└─
457  end
st   ──┘
458  
459  end
460  
461  end TM0
462  
463  namespace TM1
464  
465  section
466  parameters (Γ : Type*) [inhabited Γ] -- Type of tape symbols
id                  └───┘   └───────┘
src                          └───────┘
typ                 └───┘   └───────┘
467  parameters (Λ : Type*) -- Type of function labels
id                  └───┘
typ                 └───┘
468  parameters (σ : Type*) -- Type of variable settings
id                   └───┘
typ                  └───┘
469  
470  /-- The TM1 model is a simplification and extension of TM0
471    (Post-Turing model) in the direction of Wang B-machines. The machine's
472    internal state is extended with a (finite) store `σ` of variables
473    that may be accessed and updated at any time.
474    A machine is given by a `Λ` indexed set of procedures or functions.
475    Each function has a body which is a `stmt`, which can either be a
476    `move` or `write` command, a `branch` (if statement based on the
477    current tape value), a `load` (set the variable value),
478    a `goto` (call another function), or `halt`. Note that here
479    most statements do not have labels; `goto` commands can only
480    go to a new function. All commands have access to the variable value
481    and current tape value. -/
482  inductive stmt
483  | move : dir → stmt → stmt
id            └─┘
src           └─┘
typ           └─┘
doc           └─┘
484  | write : (Γ → σ → Γ) → stmt → stmt
id                
typ               
485  | load : (Γ → σ → σ) → stmt → stmt
id               
typ              
486  | branch : (Γ → σ → bool) → stmt → stmt → stmt
id                      └──┘
src                      └──┘
typ                     └──┘
487  | goto {} : (Γ → σ → Λ) → stmt
id                  
typ                 
488  | halt {} : stmt
489  open stmt
490  
491  instance stmt.inhabited : inhabited stmt := ⟨halt⟩
id                             └───────┘ └──┘     └──┘
src                            └───────┘ └──┘     └──┘
typ                            └───────┘ └──┘     └──┘
doc                                      └──┘
492  
493  /-- The configuration of a TM1 machine is given by the currently
494    evaluating statement, the variable store value, and the tape. -/
495  @[derive inhabited]
id            └───────┘
src           └───────┘
typ           └───────┘
doc    └────┘
496  structure cfg :=
497  (l : option Λ)
id        └────┘ 
src       └────┘
typ       └────┘ 
498  (var : σ)
id          
typ         
499  (tape : tape Γ)
id           └──┘ 
src          └──┘
typ          └──┘ 
500  
501  parameters {Γ Λ σ}
502  /-- The semantics of TM1 evaluation. -/
503  def step_aux : stmt → σ → tape Γ → cfg
id                  └──┘     └──┘    └─┘
src                 └──┘       └──┘     └─┘
typ                 └──┘     └──┘    └─┘
doc                 └──┘                └─┘
504  | (move d q)       v T := step_aux q v (T.move d)
id      └──┘               └──────┘       └───┘
src     └──┘                                  └───┘
typ     └──┘               └──────┘       └───┘
505  | (write a q)      v T := step_aux q v (T.write (a T.1 v))
id      └───┘              └──────┘       └────┘     
src     └───┘                                 └────┘     
typ     └───┘              └──────┘       └────┘     
506  | (load s q)       v T := step_aux q (s T.1 v) T
id      └──┘               └──────┘       
src     └──┘                                  
typ     └──┘               └──────┘       
507  | (branch p q₁ q₂) v T :=
id      └────┘  └┘ └┘   
src     └────┘
typ     └────┘  └┘ └┘   
508    cond (p T.1 v) (step_aux q₁ v T) (step_aux q₂ v T)
id     └──┘           └──────┘          └──────┘
src    └──┘     
typ    └──┘           └──────┘          └──────┘
509  | (goto l)         v T := ⟨some (l T.1 v), v, T⟩
id      └──┘                 └──┘     
src     └──┘                    └──┘     
typ     └──┘                 └──┘     
510  | halt             v T := ⟨none, v, T⟩
id     └──┘                   └──┘
src    └──┘                     └──┘
typ    └──┘                   └──┘
511  
512  def step (M : Λ → stmt) : cfg → option cfg
id                    └──┘    └─┘  └────┘ └─┘
src                    └──┘    └─┘   └────┘ └─┘
typ                   └──┘    └─┘  └────┘ └─┘
doc                    └──┘    └─┘          └─┘
513  | ⟨none,   v, T⟩ := none
id      └──┘             └──┘
src     └──┘             └──┘
typ     └──┘             └──┘
514  | ⟨some l, v, T⟩ := some (step_aux (M l) v T)
id      └──┘          └──┘  └──────┘  
src     └──┘             └──┘  └──────┘
typ     └──┘          └──┘  └──────┘  
doc                            └──────┘
515  
516  variables [inhabited Λ] [inhabited σ]
id              └───────┘     └───────┘
src             └───────┘     └───────┘
typ             └───────┘     └───────┘
517  def init (l : list Γ) : cfg :=
id                 └──┘     └─┘
src                └──┘      └─┘
typ                └──┘     └─┘
doc                          └─┘
518  ⟨some (default _), default _, tape.mk l⟩
id    └──┘  └─────┘     └─────┘    └─────┘ 
src   └──┘  └─────┘     └─────┘    └─────┘
typ   └──┘  └─────┘     └─────┘    └─────┘ 
519  
520  def eval (M : Λ → stmt) (l : list Γ) : roption (list Γ) :=
id                    └──┘       └──┘     └─────┘  └──┘ 
src                    └──┘       └──┘      └─────┘  └──┘
typ                   └──┘       └──┘     └─────┘  └──┘ 
doc                    └──┘                 └─────┘
521  (eval (step M) (init l)).map (λ c, c.tape.2.2)
id    └──┘  └──┘    └──┘   └─┘       └───┘ 
src   └──┘  └──┘     └──┘    └─┘         └───┘ 
typ   └──┘  └──┘    └──┘   └─┘       └───┘ 
doc                          └─┘
522  
523  variables [fintype Γ]
id              └─────┘
src             └─────┘
typ             └─────┘
doc             └─────┘
524  def supports_stmt (S : finset Λ) : stmt → Prop
id                          └────┘     └──┘ 
src                         └────┘      └──┘
typ                         └────┘     └──┘ 
doc                         └────┘      └──┘
525  | (move d q)       := supports_stmt q
id      └──┘              └───────────┘
src     └──┘
typ     └──┘              └───────────┘
526  | (write a q)      := supports_stmt q
id      └───┘             └───────────┘
src     └───┘
typ     └───┘             └───────────┘
527  | (load s q)       := supports_stmt q
id      └──┘              └───────────┘
src     └──┘
typ     └──┘              └───────────┘
528  | (branch p q₁ q₂) := supports_stmt q₁ ∧ supports_stmt q₂
id      └────┘   └┘ └┘     └───────────┘     └───────────┘
src     └────┘                              
typ     └────┘   └┘ └┘     └───────────┘     └───────────┘
529  | (goto l)         := ∀ a v, l a v ∈ S
id      └──┘                        
src     └──┘                            
typ     └──┘                        
530  | halt             := true
id     └──┘                └──┘
src    └──┘                └──┘
typ    └──┘                └──┘
531  
532  /-- A set `S` of labels supports machine `M` if all the `goto`
533    statements in the functions in `S` refer only to other functions
534    in `S`. -/
535  def supports (M : Λ → stmt) (S : finset Λ) :=
id                        └──┘       └────┘ 
src                        └──┘       └────┘
typ                       └──┘       └────┘ 
doc                        └──┘       └────┘
536  default Λ ∈ S ∧ ∀ q ∈ S, supports_stmt S (M q)
id   └─────┘            └───────────┘    
src  └─────┘                └───────────┘
typ  └─────┘            └───────────┘    
537  
538  open_locale classical
539  noncomputable def stmts₁ : stmt → finset stmt
id                              └──┘  └────┘ └──┘
src                             └──┘   └────┘ └──┘
typ                             └──┘  └────┘ └──┘
doc                             └──┘   └────┘ └──┘
540  | Q@(move d q)       := insert Q (stmts₁ q)
id        └──┘              └────┘    └────┘
src       └──┘               └────┘
typ       └──┘              └────┘    └────┘
541  | Q@(write a q)      := insert Q (stmts₁ q)
id        └───┘             └────┘    └────┘
src       └───┘              └────┘
typ       └───┘             └────┘    └────┘
542  | Q@(load s q)       := insert Q (stmts₁ q)
id        └──┘              └────┘    └────┘
src       └──┘               └────┘
typ       └──┘              └────┘    └────┘
543  | Q@(branch p q₁ q₂) := insert Q (stmts₁ q₁ ∪ stmts₁ q₂)
id        └────┘   └┘ └┘     └────┘    └────┘     └────┘
src       └────┘             └────┘              
typ       └────┘   └┘ └┘     └────┘    └────┘     └────┘
544  | Q                  := {Q}
id                          
src                          
typ                         
545  
546  theorem stmts₁_self {q} : q ∈ stmts₁ q :=
id                               └────┘ 
src                               └────┘
typ                              └────┘ 
547  by cases q; apply finset.mem_insert_self
id                    └────────────────────┘
src     └────┘   └────┘└────────────────────┘
typ     └────┘  └────┘└────────────────────┘
doc     └────┘   └────┘                      
txt     └────┘   └────┘                      
par     └────┘   └────┘                      
pid                                        
st     └──────────────────────────────────────
548  
src  
typ  
doc  
txt  
par  
pid  
st   
549  theorem stmts₁_trans {q₁ q₂} :
550    q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ :=
id     └┘  └────┘ └┘   └────┘ └┘  └────┘ └┘
src        └────┘      └────┘     └────┘
typ    └┘  └────┘ └┘   └────┘ └┘  └────┘ └┘
551  begin
st   └─────
552    intros h₁₂ q₀ h₀₁,
src    └───────────────┘
typ    └───────────────┘
doc    └───────────────┘
txt    └───────────────┘
par    └───────────────┘
pid          └─────────┘
st   ──────────────────┘└─
553    induction q₂ with _ q IH _ q IH _ q IH;
id               └┘
src    └────────┘  └────────────────────────┘
typ    └────────┘└┘└────────────────────────┘
doc    └────────┘  └────────────────────────┘
txt    └────────┘  └────────────────────────┘
par    └────────┘  └────────────────────────┘
pid               └───────────────────────┘
st   ──────────────────────────────────────────
554      simp only [stmts₁] at h₁₂ ⊢;
id                  └────┘
src      └─────────┘└────┘└────────┘
typ      └─────────┘└────┘└────────┘
doc      └─────────┘      └────────┘
txt      └─────────┘      └────────┘
par      └─────────┘      └────────┘
pid          └──┘└┘      └──────┘
st   ─────────────────────────────────
555      simp only [finset.mem_insert, finset.mem_union,
id                  └───────────────┘  └──────────────┘
src      └─────────┘└───────────────┘└┘└──────────────┘└─
typ      └─────────┘└───────────────┘└┘└──────────────┘└─
doc      └─────────┘                 └┘                └─
txt      └─────────┘                 └┘                └─
par      └─────────┘                 └┘                └─
pid          └──┘└┘                 └┘                └─
st   ────────────────────────────────────────────────────
556        finset.insert_empty_eq_singleton, finset.mem_singleton] at h₁₂,
id         └──────────────────────────────┘  └──────────────────┘
src  ─────┘└──────────────────────────────┘└┘└──────────────────┘└──────┘
typ  ─────┘└──────────────────────────────┘└┘└──────────────────┘└──────┘
doc  ─────┘                                └┘                    └──────┘
txt  ─────┘                                └┘                    └──────┘
par  ─────┘                                └┘                    └──────┘
pid  ─────┘                                └┘                    └────┘
st   ───────────────────────────────────────────────────────────────────┘└─
557    iterate 3 {
src    └───────────
typ    └───────────
doc    └───────────
txt    └───────────
par    └───────────
pid           └───
st   ──────────────
558      rcases h₁₂ with rfl | h₁₂,
id              └─┘
src  ───┘└─────┘   └─────────────┘└─
typ  ───┘└─────┘└─┘└─────────────┘└─
doc  ───┘└─────┘   └─────────────┘└─
txt  ───┘└─────┘   └─────────────┘└─
par  ───┘└─────┘   └─────────────┘└─
pid  ──────────┘   └────────────────
st   ────────────────────────────┘└─
559      { unfold stmts₁ at h₀₁, exact h₀₁ },
id                                     └─┘
src  ─────┘└──────────────────┘└┘└────┘   └──
typ  ─────┘└──────────────────┘└┘└────┘└─┘└──
doc  ─────┘└──────────────────┘└┘└────┘   └──
txt  ─────┘└──────────────────┘└┘└────┘   └──
par  ─────┘└──────────────────┘└┘└────┘   └──
pid  ─────────────────────────────────┘   └───
st   ────┘└───────────────────┘└──────────┘└─
560      { exact finset.mem_insert_of_mem (IH h₁₂) } },
id               └──────────────────────┘  └┘ └─┘
src  ─────┘└────┘└──────────────────────┘      └┘└─┘
typ  ─────┘└────┘└──────────────────────┘ └┘└─┘└┘└─┘
doc  ─────┘└────┘                              └┘└─┘
txt  ─────┘└────┘                              └┘└─┘
par  ─────┘└────┘                              └┘└─┘
pid  ───────────┘                              └───┘
st   ────┘└───────────────────────────────────────┘└─┘
561    case TM1.stmt.branch : p q₁ q₂ IH₁ IH₂ {
src    └────────────────────────────────────────
typ    └────────────────────────────────────────
doc    └────────────────────────────────────────
txt    └────────────────────────────────────────
par    └────────────────────────────────────────
pid        └──────────────┘└────────────────┘└──
st   ─────────────────────────────────────────┘
562      rcases h₁₂ with rfl | h₁₂ | h₁₂,
id              └─┘
src  ───┘└─────┘   └───────────────────┘└─
typ  ───┘└─────┘└─┘└───────────────────┘└─
doc  ───┘└─────┘   └───────────────────┘└─
txt  ───┘└─────┘   └───────────────────┘└─
par  ───┘└─────┘   └───────────────────┘└─
pid  ──────────┘   └──────────────────────
st   ──────────────────────────────────┘└─
563      { unfold stmts₁ at h₀₁, exact h₀₁ },
id                                     └─┘
src  ─────┘└──────────────────┘└┘└────┘   └──
typ  ─────┘└──────────────────┘└┘└────┘└─┘└──
doc  ─────┘└──────────────────┘└┘└────┘   └──
txt  ─────┘└──────────────────┘└┘└────┘   └──
par  ─────┘└──────────────────┘└┘└────┘   └──
pid  ─────────────────────────────────┘   └───
st   ────┘└───────────────────┘└──────────┘└─
564      { exact finset.mem_insert_of_mem (finset.mem_union_left _ $ IH₁ h₁₂) },
id               └──────────────────────┘  └───────────────────┘     └─┘ └─┘
src  ─────┘└────┘└──────────────────────┘ └───────────────────┘└─┘       └┘└──
typ  ─────┘└────┘└──────────────────────┘ └───────────────────┘└─┘ └─┘└─┘└┘└──
doc  ─────┘└────┘                                              └─┘       └┘└──
txt  ─────┘└────┘                                              └─┘       └┘└──
par  ─────┘└────┘                                              └─┘       └┘└──
pid  ───────────┘                                              └─┘       └────
st   ────┘└──────────────────────────────────────────────────────────────────┘└─
565      { exact finset.mem_insert_of_mem (finset.mem_union_right _ $ IH₂ h₁₂) } },
id               └──────────────────────┘  └────────────────────┘     └─┘ └─┘
src  ─────┘└────┘└──────────────────────┘ └────────────────────┘└─┘       └┘└─┘
typ  ─────┘└────┘└──────────────────────┘ └────────────────────┘└─┘ └─┘└─┘└┘└─┘
doc  ─────┘└────┘                                               └─┘       └┘└─┘
txt  ─────┘└────┘                                               └─┘       └┘└─┘
par  ─────┘└────┘                                               └─┘       └┘└─┘
pid  ───────────┘                                               └─┘       └───┘
st   ─────────────────────────────────────────────────────────────────────────┘└──┘
566    case TM1.stmt.goto : l {
src    └────────────────────────
typ    └────────────────────────
doc    └────────────────────────
txt    └────────────────────────
par    └────────────────────────
pid        └────────────┘└──┘└──
st   ─────────────────────────┘
567      subst h₁₂, exact h₀₁ },
id             └─┘        └─┘
src  ───┘└────┘   └┘└────┘   
typ  ───┘└────┘└─┘└┘└────┘└─┘
doc  ───┘└────┘   └┘└────┘   
txt  ───┘└────┘   └┘└────┘   
par  ───┘└────┘   └┘└────┘   
pid  ─────────┘   └──────┘   └┘
st   ────────────┘└──────────┘└┘
568    case TM1.stmt.halt {
src    └────────────────────
typ    └────────────────────
doc    └────────────────────
txt    └────────────────────
par    └────────────────────
pid        └────────────┘└─
st   ───────────────────────
569      subst h₁₂, exact h₀₁ }
id             └─┘        └─┘
src  ───┘└────┘   └┘└────┘   └┘
typ  ───┘└────┘└─┘└┘└────┘└─┘└┘
doc  ───┘└────┘   └┘└────┘   └┘
txt  ───┘└────┘   └┘└────┘   └┘
par  ───┘└────┘   └┘└────┘   └┘
pid  ─────────┘   └──────┘   └┘
st   ────────────┘└──────────┘
570  end
st   └─┘
571  
572  theorem stmts₁_supports_stmt_mono {S q₁ q₂}
573    (h : q₁ ∈ stmts₁ q₂) (hs : supports_stmt S q₂) : supports_stmt S q₁ :=
id          └┘  └────┘ └┘        └───────────┘  └┘    └───────────┘  └┘
src             └────┘           └───────────┘         └───────────┘
typ         └┘  └────┘ └┘        └───────────┘  └┘    └───────────┘  └┘
574  begin
st   └─────
575    induction q₂ with _ q IH _ q IH _ q IH;
id               └┘
src    └────────┘  └────────────────────────┘
typ    └────────┘└┘└────────────────────────┘
doc    └────────┘  └────────────────────────┘
txt    └────────┘  └────────────────────────┘
par    └────────┘  └────────────────────────┘
pid               └───────────────────────┘
st   ──────────────────────────────────────────
576      simp only [stmts₁, supports_stmt, finset.mem_insert, finset.mem_union,
id                  └────┘  └───────────┘  └───────────────┘  └──────────────┘
src      └─────────┘└────┘└┘└───────────┘└┘└───────────────┘└┘└──────────────┘└─
typ      └─────────┘└────┘└┘└───────────┘└┘└───────────────┘└┘└──────────────┘└─
doc      └─────────┘      └┘             └┘                 └┘                └─
txt      └─────────┘      └┘             └┘                 └┘                └─
par      └─────────┘      └┘             └┘                 └┘                └─
pid          └──┘└┘      └┘             └┘                 └┘                └─
st   ───────────────────────────────────────────────────────────────────────────
577        finset.insert_empty_eq_singleton, finset.mem_singleton] at h hs,
id         └──────────────────────────────┘  └──────────────────┘
src  ─────┘└──────────────────────────────┘└┘└──────────────────┘└───────┘
typ  ─────┘└──────────────────────────────┘└┘└──────────────────┘└───────┘
doc  ─────┘                                └┘                    └───────┘
txt  ─────┘                                └┘                    └───────┘
par  ─────┘                                └┘                    └───────┘
pid  ─────┘                                └┘                    └─────┘
st   ────────────────────────────────────────────────────────────────────┘└─
578    iterate 3 { rcases h with rfl | h; [exact hs, exact IH h hs] },
id                                              └┘        └┘  └┘
src    └──────────┘└─────┘ └───────────┘└─┘└────┘  └┘└────┘     └─┘
typ    └──────────┘└─────┘└───────────┘└─┘└────┘└┘└┘└────┘└┘└┘└─┘
doc    └──────────┘└─────┘ └───────────┘└─┘└────┘  └┘└────┘     └─┘
txt    └──────────┘└─────┘ └───────────┘└─┘└────┘  └┘└────┘     └─┘
par    └──────────┘└─────┘ └───────────┘└─┘└────┘  └┘└────┘     └─┘
pid           └─────────┘ └────────────────────┘  └──────┘     └─┘
st   ────────────┘└───────────────────────────────────────────────┘└─┘
579    case TM1.stmt.branch : p q₁ q₂ IH₁ IH₂ {
src    └────────────────────────────────────────
typ    └────────────────────────────────────────
doc    └────────────────────────────────────────
txt    └────────────────────────────────────────
par    └────────────────────────────────────────
pid        └──────────────┘└────────────────┘└──
st   ─────────────────────────────────────────┘
580      rcases h with rfl | h | h, exacts [hs, IH₁ h hs.1, IH₂ h hs.2] },
id                                         └┘  └─┘  └┘    └─┘  └┘
src  ───┘└─────┘ └───────────────┘└┘└──────┘  └┘      └──┘      └──┘
typ  ───┘└─────┘└───────────────┘└┘└──────┘└┘└┘└─┘└┘└──┘└─┘└┘└──┘
doc  ───┘└─────┘ └───────────────┘└┘└──────┘  └┘      └──┘      └──┘
txt  ───┘└─────┘ └───────────────┘└┘└──────┘  └┘      └──┘      └──┘
par  ───┘└─────┘ └───────────────┘└┘└──────┘  └┘      └──┘      └──┘
pid  ──────────┘ └─────────────────────────┘  └┘      └──┘      └───┘
st   ────────────────────────────┘└────────────────────────────────────┘└┘
581    case TM1.stmt.goto : l { subst h, exact hs },
id                                            └┘
src    └───────────────────────┘└────┘ └┘└────┘  
typ    └───────────────────────┘└────┘└┘└────┘└┘
doc    └───────────────────────┘└────┘ └┘└────┘  
txt    └───────────────────────┘└────┘ └┘└────┘  
par    └───────────────────────┘└────┘ └┘└────┘  
pid        └────────────┘└──┘└───────┘ └──────┘  └┘
st   ─────────────────────────┘└──────┘└─────────┘└┘
582    case TM1.stmt.halt { subst h, trivial }
id                                
src    └───────────────────┘└────┘ └┘└──────┘└┘
typ    └───────────────────┘└────┘└┘└──────┘└┘
doc    └───────────────────┘└────┘ └┘└──────┘└┘
txt    └───────────────────┘└────┘ └┘└──────┘└┘
par    └───────────────────┘└────┘ └┘└──────┘└┘
pid        └────────────┘└──────┘ └─────────┘
st   ─────────────────────────────┘└────────┘
583  end
st   └─┘
584  
585  noncomputable def stmts
586    (M : Λ → stmt) (S : finset Λ) : finset (option stmt) :=
id             └──┘       └────┘     └────┘  └────┘ └──┘
src             └──┘       └────┘      └────┘  └────┘ └──┘
typ            └──┘       └────┘     └────┘  └────┘ └──┘
doc             └──┘       └────┘      └────┘         └──┘
587  (S.bind (λ q, stmts₁ (M q))).insert_none
id    └───┘      └────┘      └─────────┘
src    └───┘       └────┘        └─────────┘
typ   └───┘      └────┘      └─────────┘
doc    └───┘
588  
589  theorem stmts_trans {M : Λ → stmt} {S q₁ q₂}
id                               └──┘
src                               └──┘
typ                              └──┘
doc                               └──┘
590    (h₁ : q₁ ∈ stmts₁ q₂) : some q₂ ∈ stmts M S → some q₁ ∈ stmts M S :=
id           └┘  └────┘ └┘    └──┘ └┘  └───┘     └──┘ └┘  └───┘  
src              └────┘       └──┘     └───┘       └──┘     └───┘
typ          └┘  └────┘ └┘    └──┘ └┘  └───┘     └──┘ └┘  └───┘  
591  by simp only [stmts, finset.mem_insert_none, finset.mem_bind,
id                 └───┘  └────────────────────┘  └─────────────┘
src     └─────────┘└───┘└┘└────────────────────┘└┘└─────────────┘└─
typ     └─────────┘└───┘└┘└────────────────────┘└┘└─────────────┘└─
doc     └─────────┘     └┘                      └┘               └─
txt     └─────────┘     └┘                      └┘               └─
par     └─────────┘     └┘                      └┘               └─
pid         └──┘└┘     └┘                      └┘               └─
st     └───────────────────────────────────────────────────────────
592    option.mem_def, forall_eq', exists_imp_distrib];
id     └────────────┘  └────────┘  └────────────────┘
src  ─┘└────────────┘└┘└────────┘└┘└────────────────┘
typ  ─┘└────────────┘└┘└────────┘└┘└────────────────┘
doc  ─┘              └┘          └┘                  
txt  ─┘              └┘          └┘                  
par  ─┘              └┘          └┘                  
pid  ─┘              └┘          └┘                  
st   ───────────────────────────────────────────────────
593  exact λ l ls h₂, ⟨_, ls, stmts₁_trans h₂ h₁⟩
id                            └──────────┘    └┘
src  └────┘ └────────┘ └─┘  └┘└──────────┘    └─
typ  └────┘ └────────┘ └─┘  └┘└──────────┘  └┘└─
doc  └────┘ └────────┘ └─┘  └┘                └─
txt  └────┘ └────────┘ └─┘  └┘                └─
par  └────┘ └────────┘ └─┘  └┘                └─
pid        └────────┘ └─┘  └┘                
st   ─────────────────────────────────────────────
594  
src  
typ  
doc  
txt  
par  
pid  
st   
595  theorem stmts_supports_stmt {M : Λ → stmt} {S q}
id                                       └──┘
src                                       └──┘
typ                                      └──┘
doc                                       └──┘
596    (ss : supports M S) : some q ∈ stmts M S → supports_stmt S q :=
id           └──────┘      └──┘   └───┘     └───────────┘  
src          └──────┘        └──┘    └───┘       └───────────┘
typ          └──────┘      └──┘   └───┘     └───────────┘  
doc          └──────┘
597  by simp only [stmts, finset.mem_insert_none, finset.mem_bind,
id                 └───┘  └────────────────────┘  └─────────────┘
src     └─────────┘└───┘└┘└────────────────────┘└┘└─────────────┘└─
typ     └─────────┘└───┘└┘└────────────────────┘└┘└─────────────┘└─
doc     └─────────┘     └┘                      └┘               └─
txt     └─────────┘     └┘                      └┘               └─
par     └─────────┘     └┘                      └┘               └─
pid         └──┘└┘     └┘                      └┘               └─
st     └───────────────────────────────────────────────────────────
598    option.mem_def, forall_eq', exists_imp_distrib];
id     └────────────┘  └────────┘  └────────────────┘
src  ─┘└────────────┘└┘└────────┘└┘└────────────────┘
typ  ─┘└────────────┘└┘└────────┘└┘└────────────────┘
doc  ─┘              └┘          └┘                  
txt  ─┘              └┘          └┘                  
par  ─┘              └┘          └┘                  
pid  ─┘              └┘          └┘                  
st   ───────────────────────────────────────────────────
599  exact λ l ls h, stmts₁_supports_stmt_mono h (ss.2 _ ls)
id                   └───────────────────────┘    └┘
src  └────┘ └───────┘└───────────────────────┘    └───┘  └─
typ  └────┘ └───────┘└───────────────────────┘  └┘└───┘  └─
doc  └────┘ └───────┘                             └───┘  └─
txt  └────┘ └───────┘                             └───┘  └─
par  └────┘ └───────┘                             └───┘  └─
pid        └───────┘                             └───┘  
st   ────────────────────────────────────────────────────────
600  
src  
typ  
doc  
txt  
par  
pid  
st   
601  theorem step_supports (M : Λ → stmt) {S}
id                                 └──┘
src                                 └──┘
typ                                └──┘
doc                                 └──┘
602    (ss : supports M S) : ∀ {c c' : cfg},
id           └──────┘               └─┘
src          └──────┘                  └─┘
typ          └──────┘               └─┘
doc          └──────┘                  └─┘
603    c' ∈ step M c → c.l ∈ S.insert_none → c'.l ∈ S.insert_none
id     └┘  └──┘     └┘  └──────────┘   └┘└┘  └──────────┘
src        └──┘        └┘   └──────────┘     └┘   └──────────┘
typ    └┘  └──┘     └┘  └──────────┘   └┘└┘  └──────────┘
604  | ⟨some l₁, v, T⟩ c' h₁ h₂ := begin
id      └──┘
src     └──┘
typ     └──┘
st                                 └─────
605    replace h₂ := ss.2 _ (finset.some_mem_insert_none.1 h₂),
id                   └┘      └─────────────────────────┘   └┘
src    └────────────┘  └───┘ └─────────────────────────┘└─┘  
typ    └────────────┘└┘└───┘ └─────────────────────────┘└─┘└┘
doc    └────────────┘  └───┘                            └─┘  
txt    └────────────┘  └───┘                            └─┘  
par    └────────────┘  └───┘                            └─┘  
pid           └─┘└─┘  └───┘                            └─┘  
st   ────────────────────────────────────────────────────────┘└─
606    simp only [step, option.mem_def] at h₁, subst c',
id                └──┘  └────────────┘               └┘
src    └─────────┘└──┘└┘└────────────┘└─────┘  └────┘
typ    └─────────┘└──┘└┘└────────────┘└─────┘  └────┘└┘
doc    └─────────┘    └┘              └─────┘  └────┘
txt    └─────────┘    └┘              └─────┘  └────┘
par    └─────────┘    └┘              └─────┘  └────┘
pid        └──┘└┘    └┘              └───┘       
st   ───────────────────────────────────────┘└────────┘└─
607    revert h₂, induction M l₁ with _ q IH _ q IH _ q IH generalizing v T;
id                           └┘
src    └───────┘  └────────┘   └─────────────────────────────────────────┘
typ    └───────┘  └────────┘└┘└─────────────────────────────────────────┘
doc    └───────┘  └────────┘   └─────────────────────────────────────────┘
txt    └───────┘  └────────┘   └─────────────────────────────────────────┘
par    └───────┘  └────────┘   └─────────────────────────────────────────┘
pid          └─┘              └───────────────────────┘└───────────────┘
st   ──────────┘└────────────────────────────────────────────────────────────
608      intro hs,
src      └──────┘
typ      └──────┘
doc      └──────┘
txt      └──────┘
par      └──────┘
pid           └─┘
st   ───────────┘└─
609    iterate 3 { exact IH _ _ hs },
id                       └┘     └┘
src    └──────────┘└────┘  └───┘  
typ    └──────────┘└────┘└┘└───┘└┘
doc    └──────────┘└────┘  └───┘  
txt    └──────────┘└────┘  └───┘  
par    └──────────┘└────┘  └───┘  
pid           └────────┘  └───┘  └┘
st   ─────────────────────────────┘└┘
610    case TM1.stmt.branch : p q₁' q₂' IH₁ IH₂ {
src    └──────────────────────────────────────────
typ    └──────────────────────────────────────────
doc    └──────────────────────────────────────────
txt    └──────────────────────────────────────────
par    └──────────────────────────────────────────
pid        └──────────────┘└──────────────────┘└──
st   ───────────────────────────────────────────┘
611      unfold step_aux, cases p T.1 v,
id                                  
src  ───┘└─────────────┘└┘└────┘  └─┘ └─
typ  ───┘└─────────────┘└┘└────┘└─┘└─
doc  ───┘└─────────────┘└┘└────┘  └─┘ └─
txt  ───┘└─────────────┘└┘└────┘  └─┘ └─
par  ───┘└─────────────┘└┘└────┘  └─┘ └─
pid  ──────────────────────────┘  └─┘ └─
st   ──────────────────┘└─────────────┘└─
612      { exact IH₂ _ _ hs.2 },
id               └─┘     └┘
src  ─────┘└────┘   └───┘  └─┘└──
typ  ─────┘└────┘└─┘└───┘└┘└─┘└──
doc  ─────┘└────┘   └───┘  └─┘└──
txt  ─────┘└────┘   └───┘  └─┘└──
par  ─────┘└────┘   └───┘  └─┘└──
pid  ───────────┘   └───┘  └─────
st   ────┘└──────────────────┘└─
613      { exact IH₁ _ _ hs.1 } },
id               └─┘     └┘
src  ─────┘└────┘   └───┘  └─┘└─┘
typ  ─────┘└────┘└─┘└───┘└┘└─┘└─┘
doc  ─────┘└────┘   └───┘  └─┘└─┘
txt  ─────┘└────┘   └───┘  └─┘└─┘
par  ─────┘└────┘   └───┘  └─┘└─┘
pid  ───────────┘   └───┘  └────┘
st   ────────────────────────┘└──┘
614    case TM1.stmt.goto { exact finset.some_mem_insert_none.2 (hs _ _) },
id                                └─────────────────────────┘    └┘
src    └───────────────────┘└────┘└─────────────────────────┘└─┘   └────┘
typ    └───────────────────┘└────┘└─────────────────────────┘└─┘ └┘└────┘
doc    └───────────────────┘└────┘                           └─┘   └────┘
txt    └───────────────────┘└────┘                           └─┘   └────┘
par    └───────────────────┘└────┘                           └─┘   └────┘
pid        └────────────┘└──────┘                           └─┘   └─────┘
st   ─────────────────────┘└────────────────────────────────────────────┘└┘
615    case TM1.stmt.halt { apply multiset.mem_cons_self }
id                                └────────────────────┘
src    └───────────────────┘└────┘└────────────────────┘└┘
typ    └───────────────────┘└────┘└────────────────────┘└┘
doc    └───────────────────┘└────┘                      └┘
txt    └───────────────────┘└────┘                      └┘
par    └───────────────────┘└────┘                      └┘
pid        └────────────┘└──────┘                      └┘
st   ───────────────────────────────────────────────────┘
616  end
st   └─┘
617  
618  end
619  
620  end TM1
621  
622  namespace TM1to0
623  
624  section
625  parameters {Γ : Type*} [inhabited Γ]
id                          └───────┘
src                          └───────┘
typ                         └───────┘
626  parameters {Λ : Type*} [inhabited Λ]
id                          └───────┘
src                          └───────┘
typ                         └───────┘
627  parameters {σ : Type*} [inhabited σ]
id                           └───────┘
src                          └───────┘
typ                          └───────┘
628  
629  local notation `stmt₁` := TM1.stmt Γ Λ σ
id                             └──────┘
src                            └──────┘
typ                            └──────┘
doc                            └──────┘
630  local notation `cfg₁` := TM1.cfg Γ Λ σ
id                            └─────┘
src                           └─────┘
typ                           └─────┘
doc                           └─────┘
631  local notation `stmt₀` := TM0.stmt Γ
id                             └──────┘
src                            └──────┘
typ                            └──────┘
doc                            └──────┘
632  
633  parameters (M : Λ → stmt₁)
id                       └───┘
src                      └───┘
typ                      └───┘
doc                      └───┘
634  include M
635  
636  def Λ' := option stmt₁ × σ
id             └────┘ └───┘  
src            └────┘ └───┘ 
typ            └────┘ └───┘  
doc                   └───┘
637  instance : inhabited Λ' := ⟨(some (M (default _)), default _)⟩
id              └───────┘ └┘     └──┘    └─────┘      └─────┘
src             └───────┘ └┘     └──┘     └─────┘      └─────┘
typ             └───────┘ └┘     └──┘    └─────┘      └─────┘
638  
639  open TM0.stmt
640  
641  def tr_aux (s : Γ) : stmt₁ → σ → Λ' × stmt₀
id                       └───┘     └┘  └───┘
src                       └───┘       └┘  └───┘
typ                      └───┘     └┘  └───┘
doc                       └───┘            └───┘
642  | (TM1.stmt.move d q)       v := ((some q, v), move d)
id      └───────────┘              └┘└──┘        └──┘
src     └───────────┘                 └┘└──┘        └──┘
typ     └───────────┘              └──┘        └──┘
643  | (TM1.stmt.write a q)      v := ((some q, v), write (a s v))
id      └────────────┘             └┘└──┘        └───┘    
src     └────────────┘                └┘└──┘        └───┘
typ     └────────────┘             └──┘        └───┘    
644  | (TM1.stmt.load a q)       v := tr_aux q (a s v)
id      └───────────┘              └────┘      
src     └───────────┘
typ     └───────────┘              └────┘      
645  | (TM1.stmt.branch p q₁ q₂) v := cond (p s v) (tr_aux q₁ v) (tr_aux q₂ v)
id      └─────────────┘  └┘ └┘      └──┘         └────┘        └────┘
src     └─────────────┘               └──┘
typ     └─────────────┘  └┘ └┘      └──┘         └────┘        └────┘
646  | (TM1.stmt.goto l)         v := ((some (M (l s v)), v), write s)
id      └───────────┘               └┘└──┘                └───┘ 
src     └───────────┘                 └┘└──┘                  └───┘
typ     └───────────┘               └──┘                └───┘ 
647  | TM1.stmt.halt             v := ((none, v), write s)
id     └───────────┘                 └┘└──┘      └───┘ 
src    └───────────┘                  └┘└──┘      └───┘
typ    └───────────┘                 └──┘      └───┘ 
648  
649  local notation `cfg₀` := TM0.cfg Γ Λ'
id                            └─────┘
src                           └─────┘
typ                           └─────┘
doc                           └─────┘
650  
651  def tr : TM0.machine Γ Λ'
id            └─────────┘  └┘
src           └─────────┘   └┘
typ           └─────────┘  └┘
doc           └─────────┘
652  | (none,   v) s := none
id     └──┘            └──┘
src    └──┘            └──┘
typ    └──┘            └──┘
653  | (some q, v) s := some (tr_aux s q v)
id     └──┘         └──┘  └────┘
src    └──┘            └──┘  └────┘
typ    └──┘         └──┘  └────┘
654  
655  def tr_cfg : cfg₁ → cfg₀
id                └──┘  └──┘
src               └──┘   └──┘
typ               └──┘  └──┘
doc               └──┘   └──┘
656  | ⟨l, v, T⟩ := ⟨(l.map M, v), T⟩
id                 └──┘ 
src                   └──┘
typ                └──┘ 
657  
658  theorem tr_respects : respects (TM1.step M) (TM0.step tr)
id                         └──────┘  └──────┘    └──────┘ └┘
src                        └──────┘  └──────┘     └──────┘ └┘
typ                        └──────┘  └──────┘    └──────┘ └┘
doc                                               └──────┘
659    (λ c₁ c₂, tr_cfg c₁ = c₂) :=
id        └┘ └┘  └────┘ └┘  └┘
src              └────┘    
typ       └┘ └┘  └────┘ └┘  └┘
660  fun_respects.2 $ λ ⟨l₁, v, T⟩, begin
id   └──────────┘      
src  └──────────┘
typ  └──────────┘      
st                                  └─────
661    cases l₁ with l₁, {exact rfl},
id           └┘                 └─┘
src    └────┘  └──────┘   └────┘└─┘
typ    └────┘└┘└──────┘   └────┘└─┘
doc    └────┘  └──────┘   └────┘
txt    └────┘  └──────┘   └────┘
par    └────┘  └──────┘   └────┘
pid           └──────┘        
st   ─────────────────┘└──────────┘└┘
662    unfold tr_cfg TM1.step frespects option.map function.comp option.bind,
src    └───────────────────────────────────────────────────────────────────┘
typ    └───────────────────────────────────────────────────────────────────┘
doc    └───────────────────────────────────────────────────────────────────┘
txt    └───────────────────────────────────────────────────────────────────┘
par    └───────────────────────────────────────────────────────────────────┘
pid          └─────────────────────────────────────────────────────────────┘
st   ──────────────────────────────────────────────────────────────────────┘└─
663    induction M l₁ with _ q IH _ q IH _ q IH generalizing v T,
id                └┘
src    └────────┘   └─────────────────────────────────────────┘
typ    └────────┘└┘└─────────────────────────────────────────┘
doc    └────────┘   └─────────────────────────────────────────┘
txt    └────────┘   └─────────────────────────────────────────┘
par    └────────┘   └─────────────────────────────────────────┘
pid                └───────────────────────┘└───────────────┘
st   ──────────────────────────────────────────────────────────┘└─
664    case TM1.stmt.move  : d q IH { exact trans_gen.head rfl (IH _ _) },
id                                          └────────────┘ └─┘  └┘
src    └─────────────────────────────┘└────┘└────────────┘└─┘   └────┘
typ    └─────────────────────────────┘└────┘└────────────┘└─┘ └┘└────┘
doc    └─────────────────────────────┘└────┘                    └────┘
txt    └─────────────────────────────┘└────┘                    └────┘
par    └─────────────────────────────┘└────┘                    └────┘
pid        └────────────┘└────────┘└───────┘                    └─────┘
st   ───────────────────────────────┘└─────────────────────────────────┘└┘
665    case TM1.stmt.write : a q IH { exact trans_gen.head rfl (IH _ _) },
id                                          └────────────┘ └─┘  └┘
src    └─────────────────────────────┘└────┘└────────────┘└─┘   └────┘
typ    └─────────────────────────────┘└────┘└────────────┘└─┘ └┘└────┘
doc    └─────────────────────────────┘└────┘                    └────┘
txt    └─────────────────────────────┘└────┘                    └────┘
par    └─────────────────────────────┘└────┘                    └────┘
pid        └─────────────┘└───────┘└───────┘                    └─────┘
st   ───────────────────────────────┘└─────────────────────────────────┘└┘
666    case TM1.stmt.load : a q IH { exact (reaches₁_eq (by refl)).2 (IH _ _) },
id                                          └─────────┘               └┘
src    └────────────────────────────┘└────┘ └─────────┘   └──┘└───┘   └────┘
typ    └────────────────────────────┘└────┘ └─────────┘   └──┘└───┘ └┘└────┘
doc    └────────────────────────────┘└────┘               └──┘└───┘   └────┘
txt    └────────────────────────────┘└────┘               └──┘└───┘   └────┘
par    └────────────────────────────┘└────┘               └──┘└───┘   └────┘
pid        └────────────┘└───────┘└───────┘               └────────┘   └─────┘
st   ──────────────────────────────┘└─────────────────────┘└───┘└────────────┘└┘
667    case TM1.stmt.branch : p q₁ q₂ IH₁ IH₂ {
src    └────────────────────────────────────────
typ    └────────────────────────────────────────
doc    └────────────────────────────────────────
txt    └────────────────────────────────────────
par    └────────────────────────────────────────
pid        └──────────────┘└────────────────┘└──
st   ─────────────────────────────────────────┘
668      unfold TM1.step_aux, cases e : p T.1 v,
id                                          
src  ───┘└─────────────────┘└┘└────┘ └─┘  └─┘ └─
typ  ───┘└─────────────────┘└┘└────┘ └─┘└─┘└─
doc  ───┘└─────────────────┘└┘└────┘ └─┘  └─┘ └─
txt  ───┘└─────────────────┘└┘└────┘ └─┘  └─┘ └─
par  ───┘└─────────────────┘└┘└────┘ └─┘  └─┘ └─
pid  ──────────────────────────────┘ └─┘  └─┘ └─
st   ──────────────────────┘└─────────────────┘└─
669      { exact (reaches₁_eq (by simp only [TM0.step, tr, tr_aux, e]; refl)).2 (IH₂ _ _) },
id                └─────────┘                └──────┘  └┘  └────┘               └─┘
src  ─────┘└────┘ └─────────┘   └─────────┘└──────┘└┘└┘└┘└────┘└┘ └┘└──┘└───┘    └────┘└──
typ  ─────┘└────┘ └─────────┘   └─────────┘└──────┘└┘└┘└┘└────┘└┘└┘└──┘└───┘ └─┘└────┘└──
doc  ─────┘└────┘               └─────────┘└──────┘└┘  └┘      └┘ └┘└──┘└───┘    └────┘└──
txt  ─────┘└────┘               └─────────┘        └┘  └┘      └┘ └┘└──┘└───┘    └────┘└──
par  ─────┘└────┘               └─────────┘        └┘  └┘      └┘ └┘└──┘└───┘    └────┘└──
pid  ───────────┘               └──────────┘        └┘  └┘      └┘ └──────────┘    └────────
st   ────┘└─────────────────────┘└────────────────────────────────────────┘└─────────────┘└─
670      { exact (reaches₁_eq (by simp only [TM0.step, tr, tr_aux, e]; refl)).2 (IH₁ _ _) } },
id                └─────────┘                └──────┘  └┘  └────┘               └─┘
src  ─────┘└────┘ └─────────┘   └─────────┘└──────┘└┘└┘└┘└────┘└┘ └┘└──┘└───┘    └────┘└─┘
typ  ─────┘└────┘ └─────────┘   └─────────┘└──────┘└┘└┘└┘└────┘└┘└┘└──┘└───┘ └─┘└────┘└─┘
doc  ─────┘└────┘               └─────────┘└──────┘└┘  └┘      └┘ └┘└──┘└───┘    └────┘└─┘
txt  ─────┘└────┘               └─────────┘        └┘  └┘      └┘ └┘└──┘└───┘    └────┘└─┘
par  ─────┘└────┘               └─────────┘        └┘  └┘      └┘ └┘└──┘└───┘    └────┘└─┘
pid  ───────────┘               └──────────┘        └┘  └┘      └┘ └──────────┘    └───────┘
st   ───────────────────────────┘└────────────────────────────────────────┘└─────────────┘└──┘
671    iterate 2 {
src    └───────────
typ    └───────────
doc    └───────────
txt    └───────────
par    └───────────
pid           └───
st   ──────────────
672      exact trans_gen.single (congr_arg some
id             └──────────────┘            └──┘
src  ───┘└────┘└──────────────┘          └──┘
typ  ───┘└────┘└──────────────┘          └──┘
doc  ───┘└────┘                              
txt  ───┘└────┘                              
par  ───┘└────┘                              
pid  ─────────┘                              
st   ───────────────────────────────────────────
673        (congr (congr_arg TM0.cfg.mk rfl) (tape.write_self T))) }
id          └───┘  └───────┘ └────────┘ └─┘   └─────────────┘ 
src  ─────┘ └───┘ └───────┘└────────┘└─┘└┘ └─────────────┘ └──┘└┘
typ  ─────┘ └───┘ └───────┘└────────┘└─┘└┘ └─────────────┘└──┘└┘
doc  ─────┘                             └┘                 └──┘└┘
txt  ─────┘                             └┘                 └──┘└┘
par  ─────┘                             └┘                 └──┘└┘
pid  ─────┘                             └┘                 └───┘
st   ─────────────────────────────────────────────────────────────┘
674  end
st   └─┘
675  
676  variables [fintype Γ] [fintype σ]
id              └─────┘     └─────┘
src             └─────┘     └─────┘
typ             └─────┘     └─────┘
doc             └─────┘     └─────┘
677  noncomputable def tr_stmts (S : finset Λ) : finset Λ' :=
id                                   └────┘     └────┘ └┘
src                                  └────┘      └────┘ └┘
typ                                  └────┘     └────┘ └┘
doc                                  └────┘      └────┘
678  (TM1.stmts M S).product finset.univ
id    └───────┘   └─────┘  └─────────┘
src   └───────┘     └─────┘  └─────────┘
typ   └───────┘   └─────┘  └─────────┘
doc                 └─────┘  └─────────┘
679  
680  open_locale classical
681  local attribute [simp] TM1.stmts₁_self
id                          └─────────────┘
src                         └─────────────┘
typ                         └─────────────┘
doc                   └──┘
682  theorem tr_supports {S : finset Λ} (ss : TM1.supports M S) :
id                            └────┘         └──────────┘  
src                           └────┘          └──────────┘
typ                           └────┘         └──────────┘  
doc                           └────┘          └──────────┘
683    TM0.supports tr (↑(tr_stmts S)) :=
id     └──────────┘ └┘   └──────┘ 
src    └──────────┘ └┘   └──────┘
typ    └──────────┘ └┘   └──────┘ 
doc    └──────────┘
684  ⟨finset.mem_product.2 ⟨finset.some_mem_insert_none.2
id    └────────────────┘   └─────────────────────────┘
src   └────────────────┘   └─────────────────────────┘
typ   └────────────────┘   └─────────────────────────┘
685    (finset.mem_bind.2 ⟨_, ss.1, TM1.stmts₁_self⟩),
id      └─────────────┘      └┘   └─────────────┘
src     └─────────────┘           └─────────────┘
typ     └─────────────┘      └┘   └─────────────┘
686    finset.mem_univ _⟩,
id     └─────────────┘
src    └─────────────┘
typ    └─────────────┘
687   λ q a q' s h₁ h₂, begin
id        └┘  └┘ └┘
typ       └┘  └┘ └┘
st                      └─────
688    rcases q with ⟨_|q, v⟩, {cases h₁},
id                                   └┘
src    └─────┘ └────────────┘   └────┘
typ    └─────┘└────────────┘   └────┘└┘
doc    └─────┘ └────────────┘   └────┘
txt    └─────┘ └────────────┘   └────┘
par    └─────┘ └────────────┘   └────┘
pid           └────────────┘        
st   ───────────────────────┘└─────────┘└┘
689    cases q' with q' v', simp only [tr_stmts, finset.mem_coe,
id           └┘                        └──────┘  └────────────┘
src    └────┘  └─────────┘  └─────────┘└──────┘└┘└────────────┘└─
typ    └────┘└┘└─────────┘  └─────────┘└──────┘└┘└────────────┘└─
doc    └────┘  └─────────┘  └─────────┘        └┘              └─
txt    └────┘  └─────────┘  └─────────┘        └┘              └─
par    └────┘  └─────────┘  └─────────┘        └┘              └─
pid           └─────────┘      └──┘└┘        └┘              └─
st   ────────────────────┘└──────────────────────────────────────
690      finset.mem_product, finset.mem_univ, and_true] at h₂ ⊢,
id       └────────────────┘  └─────────────┘  └──────┘
src  ───┘└────────────────┘└┘└─────────────┘└┘└──────┘└───────┘
typ  ───┘└────────────────┘└┘└─────────────┘└┘└──────┘└───────┘
doc  ───┘                  └┘               └┘        └───────┘
txt  ───┘                  └┘               └┘        └───────┘
par  ───┘                  └┘               └┘        └───────┘
pid  ───┘                  └┘               └┘        └─────┘
st   ─────────────────────────────────────────────────────────┘└─
691    cases q', {exact multiset.mem_cons_self _ _},
id           └┘         └────────────────────┘
src    └────┘     └────┘└────────────────────┘└──┘
typ    └────┘└┘   └────┘└────────────────────┘└──┘
doc    └────┘     └────┘                      └──┘
txt    └────┘     └────┘                      └──┘
par    └────┘     └────┘                      └──┘
pid                                         └──┘
st   ─────────┘└─────────────────────────────────┘└┘
692    simp only [tr, option.mem_def] at h₁,
id                └┘  └────────────┘
src    └─────────┘└┘└┘└────────────┘└─────┘
typ    └─────────┘└┘└┘└────────────┘└─────┘
doc    └─────────┘  └┘              └─────┘
txt    └─────────┘  └┘              └─────┘
par    └─────────┘  └┘              └─────┘
pid        └──┘└┘  └┘              └───┘
st   ─────────────────────────────────────┘└─
693    have := TM1.stmts_supports_stmt ss h₂,
id             └─────────────────────┘ └┘ └┘
src    └──────┘└─────────────────────┘  
typ    └──────┘└─────────────────────┘└┘└┘
doc    └──────┘                         
txt    └──────┘                         
par    └──────┘                         
pid    └───┘└─┘                         
st   ──────────────────────────────────────┘└─
694    revert this, induction q generalizing v; intro hs,
id                            
src    └─────────┘  └────────┘ └─────────────┘  └──────┘
typ    └─────────┘  └────────┘└─────────────┘  └──────┘
doc    └─────────┘  └────────┘ └─────────────┘  └──────┘
txt    └─────────┘  └────────┘ └─────────────┘  └──────┘
par    └─────────┘  └────────┘ └─────────────┘  └──────┘
pid          └───┘            └────────────┘       └─┘
st   ────────────┘└────────────────────────────────────┘└─
695    case TM1.stmt.move : d q {
src    └──────────────────────────
typ    └──────────────────────────
doc    └──────────────────────────
txt    └──────────────────────────
par    └──────────────────────────
pid        └────────────┘└────┘└──
st   ───────────────────────────┘
696      cases h₁, refine TM1.stmts_trans _ h₂,
id             └┘         └─────────────┘   └┘
src  ───┘└────┘  └┘└─────┘└─────────────┘└─┘  └─
typ  ───┘└────┘└┘└┘└─────┘└─────────────┘└─┘└┘└─
doc  ───┘└────┘  └┘└─────┘               └─┘  └─
txt  ───┘└────┘  └┘└─────┘               └─┘  └─
par  ───┘└────┘  └┘└─────┘               └─┘  └─
pid  ─────────┘  └───────┘               └─┘  └─
st   ───────────┘└───────────────────────────┘└─
697      unfold TM1.stmts₁,
src  ───┘└───────────────┘└─
typ  ───┘└───────────────┘└─
doc  ───┘└───────────────┘└─
txt  ───┘└───────────────┘└─
par  ───┘└───────────────┘└─
pid  ───────────────────────
st   ────────────────────┘└─
698      exact finset.mem_insert_of_mem TM1.stmts₁_self },
id             └──────────────────────┘ └─────────────┘
src  ───┘└────┘└──────────────────────┘└─────────────┘
typ  ───┘└────┘└──────────────────────┘└─────────────┘
doc  ───┘└────┘                                       
txt  ───┘└────┘                                       
par  ───┘└────┘                                       
pid  ─────────┘                                       └┘
st   ──────────────────────────────────────────────────┘└┘
699    case TM1.stmt.write : b q {
src    └───────────────────────────
typ    └───────────────────────────
doc    └───────────────────────────
txt    └───────────────────────────
par    └───────────────────────────
pid        └─────────────┘└────┘└──
st   ────────────────────────────┘
700      cases h₁, refine TM1.stmts_trans _ h₂,
id             └┘         └─────────────┘   └┘
src  ───┘└────┘  └┘└─────┘└─────────────┘└─┘  └─
typ  ───┘└────┘└┘└┘└─────┘└─────────────┘└─┘└┘└─
doc  ───┘└────┘  └┘└─────┘               └─┘  └─
txt  ───┘└────┘  └┘└─────┘               └─┘  └─
par  ───┘└────┘  └┘└─────┘               └─┘  └─
pid  ─────────┘  └───────┘               └─┘  └─
st   ───────────┘└───────────────────────────┘└─
701      unfold TM1.stmts₁,
src  ───┘└───────────────┘└─
typ  ───┘└───────────────┘└─
doc  ───┘└───────────────┘└─
txt  ───┘└───────────────┘└─
par  ───┘└───────────────┘└─
pid  ───────────────────────
st   ────────────────────┘└─
702      exact finset.mem_insert_of_mem TM1.stmts₁_self },
id             └──────────────────────┘ └─────────────┘
src  ───┘└────┘└──────────────────────┘└─────────────┘
typ  ───┘└────┘└──────────────────────┘└─────────────┘
doc  ───┘└────┘                                       
txt  ───┘└────┘                                       
par  ───┘└────┘                                       
pid  ─────────┘                                       └┘
st   ──────────────────────────────────────────────────┘└┘
703    case TM1.stmt.load : b q IH {
src    └─────────────────────────────
typ    └─────────────────────────────
doc    └─────────────────────────────
txt    └─────────────────────────────
par    └─────────────────────────────
pid        └────────────┘└───────┘└──
st   ──────────────────────────────┘
704      refine IH (TM1.stmts_trans _ h₂) _ h₁ hs,
id              └┘  └─────────────┘   └┘    └┘ └┘
src  ───┘└─────┘   └─────────────┘└─┘  └──┘    └─
typ  ───┘└─────┘└┘ └─────────────┘└─┘└┘└──┘└┘└┘└─
doc  ───┘└─────┘                  └─┘  └──┘    └─
txt  ───┘└─────┘                  └─┘  └──┘    └─
par  ───┘└─────┘                  └─┘  └──┘    └─
pid  ──────────┘                  └─┘  └──┘    └─
st   ───────────────────────────────────────────┘└─
705      unfold TM1.stmts₁,
src  ───┘└───────────────┘└─
typ  ───┘└───────────────┘└─
doc  ───┘└───────────────┘└─
txt  ───┘└───────────────┘└─
par  ───┘└───────────────┘└─
pid  ───────────────────────
st   ────────────────────┘└─
706      exact finset.mem_insert_of_mem TM1.stmts₁_self },
id             └──────────────────────┘ └─────────────┘
src  ───┘└────┘└──────────────────────┘└─────────────┘
typ  ───┘└────┘└──────────────────────┘└─────────────┘
doc  ───┘└────┘                                       
txt  ───┘└────┘                                       
par  ───┘└────┘                                       
pid  ─────────┘                                       └┘
st   ──────────────────────────────────────────────────┘└┘
707    case TM1.stmt.branch : p q₁ q₂ IH₁ IH₂ {
src    └────────────────────────────────────────
typ    └────────────────────────────────────────
doc    └────────────────────────────────────────
txt    └────────────────────────────────────────
par    └────────────────────────────────────────
pid        └──────────────┘└────────────────┘└──
st   ─────────────────────────────────────────┘
708      change cond (p a v) _ _ = ((some q', v'), s) at h₁,
id              └──┘            └──┘ └┘  └┘   
src  ───┘└─────┘└──┘    └────┘ └──┘  └┘  └─┘ └─────┘└─
typ  ───┘└─────┘└──┘ └────┘ └──┘└┘└┘└┘└─┘└─────┘└─
doc  ───┘└─────┘        └────┘         └┘  └─┘ └─────┘└─
txt  ───┘└─────┘        └────┘         └┘  └─┘ └─────┘└─
par  ───┘└─────┘        └────┘         └┘  └─┘ └─────┘└─
pid  ──────────┘        └────┘         └┘  └─┘ └────────
st   ─────────────────────────────────────────────────────┘└─
709      cases p a v,
id               
src  ───┘└────┘   └─
typ  ───┘└────┘└─
doc  ───┘└────┘   └─
txt  ───┘└────┘   └─
par  ───┘└────┘   └─
pid  ─────────┘   └─
st   ──────────────┘└─
710      { refine IH₂ (TM1.stmts_trans _ h₂) _ h₁ hs.2,
id                └─┘  └─────────────┘   └┘    └┘ └┘
src  ─────┘└─────┘    └─────────────┘└─┘  └──┘    └┘└─
typ  ─────┘└─────┘└─┘ └─────────────┘└─┘└┘└──┘└┘└┘└┘└─
doc  ─────┘└─────┘                   └─┘  └──┘    └┘└─
txt  ─────┘└─────┘                   └─┘  └──┘    └┘└─
par  ─────┘└─────┘                   └─┘  └──┘    └┘└─
pid  ────────────┘                   └─┘  └──┘    └───
st   ────┘└──────────────────────────────────────────┘└─
711        unfold TM1.stmts₁,
src  ─────┘└───────────────┘└─
typ  ─────┘└───────────────┘└─
doc  ─────┘└───────────────┘└─
txt  ─────┘└───────────────┘└─
par  ─────┘└───────────────┘└─
pid  ─────────────────────────
st   ──────────────────────┘└─
712        exact finset.mem_insert_of_mem (finset.mem_union_right _ TM1.stmts₁_self) },
id               └──────────────────────┘  └────────────────────┘   └─────────────┘
src  ─────┘└────┘└──────────────────────┘ └────────────────────┘└─┘└─────────────┘└┘└──
typ  ─────┘└────┘└──────────────────────┘ └────────────────────┘└─┘└─────────────┘└┘└──
doc  ─────┘└────┘                                               └─┘               └┘└──
txt  ─────┘└────┘                                               └─┘               └┘└──
par  ─────┘└────┘                                               └─┘               └┘└──
pid  ───────────┘                                               └─┘               └────
st   ───────────────────────────────────────────────────────────────────────────────┘└─
713      { refine IH₁ (TM1.stmts_trans _ h₂) _ h₁ hs.1,
id                └─┘  └─────────────┘   └┘    └┘ └┘
src  ─────┘└─────┘    └─────────────┘└─┘  └──┘    └┘└─
typ  ─────┘└─────┘└─┘ └─────────────┘└─┘└┘└──┘└┘└┘└┘└─
doc  ─────┘└─────┘                   └─┘  └──┘    └┘└─
txt  ─────┘└─────┘                   └─┘  └──┘    └┘└─
par  ─────┘└─────┘                   └─┘  └──┘    └┘└─
pid  ────────────┘                   └─┘  └──┘    └───
st   ────────────────────────────────────────────────┘└─
714        unfold TM1.stmts₁,
src  ─────┘└───────────────┘└─
typ  ─────┘└───────────────┘└─
doc  ─────┘└───────────────┘└─
txt  ─────┘└───────────────┘└─
par  ─────┘└───────────────┘└─
pid  ─────────────────────────
st   ──────────────────────┘└─
715        exact finset.mem_insert_of_mem (finset.mem_union_left _ TM1.stmts₁_self) } },
id               └──────────────────────┘  └───────────────────┘   └─────────────┘
src  ─────┘└────┘└──────────────────────┘ └───────────────────┘└─┘└─────────────┘└┘└─┘
typ  ─────┘└────┘└──────────────────────┘ └───────────────────┘└─┘└─────────────┘└┘└─┘
doc  ─────┘└────┘                                              └─┘               └┘└─┘
txt  ─────┘└────┘                                              └─┘               └┘└─┘
par  ─────┘└────┘                                              └─┘               └┘└─┘
pid  ───────────┘                                              └─┘               └───┘
st   ──────────────────────────────────────────────────────────────────────────────┘└──┘
716    case TM1.stmt.goto : l {
src    └────────────────────────
typ    └────────────────────────
doc    └────────────────────────
txt    └────────────────────────
par    └────────────────────────
pid        └────────────┘└──┘└──
st   ─────────────────────────┘
717      cases h₁, exact finset.some_mem_insert_none.2
id             └┘        └─────────────────────────┘
src  ───┘└────┘  └┘└────┘└─────────────────────────┘└──
typ  ───┘└────┘└┘└┘└────┘└─────────────────────────┘└──
doc  ───┘└────┘  └┘└────┘                           └──
txt  ───┘└────┘  └┘└────┘                           └──
par  ───┘└────┘  └┘└────┘                           └──
pid  ─────────┘  └──────┘                           └──
st   ───────────┘└─────────────────────────────────────
718        (finset.mem_bind.2 ⟨_, hs _ _, TM1.stmts₁_self⟩) },
id          └─────────────┘       └┘      └─────────────┘
src  ─────┘ └─────────────┘└─┘ └─┘  └────┘└─────────────┘└─┘
typ  ─────┘ └─────────────┘└─┘ └─┘└┘└────┘└─────────────┘└─┘
doc  ─────┘                └─┘ └─┘  └────┘               └─┘
txt  ─────┘                └─┘ └─┘  └────┘               └─┘
par  ─────┘                └─┘ └─┘  └────┘               └─┘
pid  ─────┘                └─┘ └─┘  └────┘               └──┘
st   ──────────────────────────────────────────────────────┘└┘
719    case TM1.stmt.halt { cases h₁ }
id                                └┘
src    └───────────────────┘└────┘  └┘
typ    └───────────────────┘└────┘└┘└┘
doc    └───────────────────┘└────┘  └┘
txt    └───────────────────┘└────┘  └┘
par    └───────────────────┘└────┘  └┘
pid        └────────────┘└──────┘  └┘
st   ───────────────────────────────┘
720  end⟩
st   └─┘
721  
722  theorem tr_eval (l : list Γ) : TM0.eval tr l = TM1.eval M l :=
id                        └──┘     └──────┘ └┘   └──────┘  
src                       └──┘      └──────┘ └┘    └──────┘
typ                       └──┘     └──────┘ └┘   └──────┘  
doc                                 └──────┘
723  (congr_arg _ (tr_eval' _ _ _ tr_respects ⟨some _, _, _⟩)).trans begin
id    └───────┘    └──────┘       └─────────┘  └──┘           └───┘
src   └───────┘    └──────┘       └─────────┘  └──┘           └───┘
typ   └───────┘    └──────┘       └─────────┘  └──┘           └───┘
st                                                                   └─────
724    rw [roption.map_eq_map, roption.map_map, TM1.eval],
id         └────────────────┘  └─────────────┘  └──────┘
src    └──┘└────────────────┘└┘└─────────────┘└┘└──────┘
typ    └──┘└────────────────┘└┘└─────────────┘└┘└──────┘
doc    └──┘                  └┘               └┘        
txt    └──┘                  └┘               └┘        
par    └──┘                  └┘               └┘        
pid      └┘                  └┘               └┘        
st   ───────────────────────┘└───────────────┘└────────┘└──
725    congr', exact funext (λ ⟨_, _, _⟩, rfl)
id                   └────┘               └─┘
src    └────┘  └────┘└────┘  └──────────┘└─┘└┘
typ    └────┘  └────┘└────┘  └──────────┘└─┘└┘
doc    └────┘  └────┘        └──────────┘   └┘
txt    └────┘  └────┘        └──────────┘   └┘
par    └────┘  └────┘        └──────────┘   └┘
pid                         └──────────┘   
st   ───────┘└────────────────────────────────┘
726  end
st   └─┘
727  
728  end
729  end TM1to0
730  
731  /- Reduce an n-symbol Turing machine to a 2-symbol Turing machine -/
732  namespace TM1to1
733  open TM1
734  
735  section
736  parameters {Γ : Type*} [inhabited Γ]
id                          └───────┘
src                          └───────┘
typ                         └───────┘
737  
738  theorem exists_enc_dec [fintype Γ] :
id                           └─────┘ 
src                          └─────┘
typ                          └─────┘ 
doc                          └─────┘
739    ∃ n (enc : Γ → vector bool n) (dec : vector bool n → Γ),
id                └────┘ └──┘          └────┘ └──┘    
src                  └────┘ └──┘           └────┘ └──┘       
typ               └────┘ └──┘          └────┘ └──┘    
740      enc (default _) = vector.repeat ff n ∧ ∀ a, dec (enc a) = a :=
id       └─┘  └─────┘     └───────────┘ └┘       └─┘  └─┘    
src           └─────┘     └───────────┘ └┘                     
typ      └─┘  └─────┘     └───────────┘ └┘       └─┘  └─┘    
741  begin
st   └─────
742    rcases fintype.exists_equiv_fin Γ with ⟨n, ⟨F⟩⟩,
id            └──────────────────────┘ 
src    └─────┘└──────────────────────┘ └────────────┘
typ    └─────┘└──────────────────────┘└────────────┘
doc    └─────┘                         └────────────┘
txt    └─────┘                         └────────────┘
par    └─────┘                         └────────────┘
pid                                   └────────────┘
st   ────────────────────────────────────────────────┘└─
743    let G : fin n ↪ fin n → bool := ⟨λ a b, a = b,
id                    └─┘    └──┘              
src    └──────┘    └─┘  └──┘└──┘  └────┘  └─
typ    └──────┘    └─┘ └──┘└──┘  └────┘  └─
doc    └──────┘              └──┘  └────┘   └─
txt    └──────┘              └──┘  └────┘   └─
par    └──────┘              └──┘  └────┘   └─
pid    └───┘└─┘              └──┘  └────┘   └─
st   ─────────────────────────────────────────────────
744      λ a b h, of_to_bool_true $ (congr_fun h b).trans $ to_bool_tt rfl⟩,
id                └─────────────┘    └───────┘              └────────┘ └─┘
src  ───┘ └──────┘└─────────────┘  └───────┘  └──────┘ └────────┘└─┘
typ  ───┘ └──────┘└─────────────┘  └───────┘  └──────┘ └────────┘└─┘
doc  ───┘ └──────┘                            └──────┘              
txt  ───┘ └──────┘                            └──────┘              
par  ───┘ └──────┘                            └──────┘              
pid  ───┘ └──────┘                            └──────┘              
st   ─────────────────────────────────────────────────────────────────────┘└─
745    let H := (F.to_embedding.trans G).trans
id               └──────────────────┘ 
src    └───────┘ └──────────────────┘ └───────
typ    └───────┘ └──────────────────┘└───────
doc    └───────┘                      └───────
txt    └───────┘                      └───────
par    └───────┘                      └───────
pid    └───┘└─┘                      └───────
st   ──────────────────────────────────────────
746      (equiv.vector_equiv_fin _ _).symm.to_embedding,
id        └────────────────────┘
src  ───┘ └────────────────────┘└─────────────────────┘
typ  ───┘ └────────────────────┘└─────────────────────┘
doc  ───┘                       └─────────────────────┘
txt  ───┘                       └─────────────────────┘
par  ───┘                       └─────────────────────┘
pid  ───┘                       └────────────────────┘
st   ─────────────────────────────────────────────────┘└─
747    let enc := H.set_value (default _) (vector.repeat ff n),
id                └─────────┘  └─────┘     └───────────┘ └┘ 
src    └─────────┘└─────────┘ └─────┘└──┘ └───────────┘└┘ 
typ    └─────────┘└─────────┘ └─────┘└──┘ └───────────┘└┘
doc    └─────────┘                   └──┘                 
txt    └─────────┘                   └──┘                 
par    └─────────┘                   └──┘                 
pid    └─────┘└─┘                   └──┘                 
st   ────────────────────────────────────────────────────────┘└─
748    exact ⟨_, enc, function.inv_fun enc,
id                    └──────────────┘
src    └────┘ └─┘   └┘└──────────────┘   └─
typ    └────┘ └─┘   └┘└──────────────┘   └─
doc    └────┘ └─┘   └┘└──────────────┘   └─
txt    └────┘ └─┘   └┘                   └─
par    └────┘ └─┘   └┘                   └─
pid          └─┘   └┘                   └─
st   ───────────────────────────────────────
749      H.set_value_eq _ _, function.left_inverse_inv_fun enc.2⟩
id       └────────────┘      └───────────────────────────┘ └─┘
src  ───┘└────────────┘└────┘└───────────────────────────┘   └──┘
typ  ───┘└────────────┘└────┘└───────────────────────────┘└─┘└──┘
doc  ───┘              └────┘                                └──┘
txt  ───┘              └────┘                                └──┘
par  ───┘              └────┘                                └──┘
pid  ───┘              └────┘                                └─┘
st   ────────────────────────────────────────────────────────────┘
750  end
st   └─┘
751  
752  parameters {Λ : Type*} [inhabited Λ]
id                           └───────┘
src                          └───────┘
typ                          └───────┘
753  parameters {σ : Type*} [inhabited σ]
id                           └───────┘
src                          └───────┘
typ                          └───────┘
754  
755  local notation `stmt₁` := stmt Γ Λ σ
id                             └──┘
src                            └──┘
typ                            └──┘
doc                            └──┘
756  local notation `cfg₁` := cfg Γ Λ σ
id                            └─┘
src                           └─┘
typ                           └─┘
doc                           └─┘
757  
758  inductive Λ' : Type (max u_1 u_2 u_3)
759  | normal : Λ → Λ'
760  | write : Γ → stmt₁ → Λ'
id                 └───┘
src                └───┘
typ                └───┘
doc                └───┘
761  instance : inhabited Λ' := ⟨Λ'.normal (default _)⟩
id              └───────┘ └┘     └───────┘  └─────┘
src             └───────┘ └┘     └───────┘  └─────┘
typ             └───────┘ └┘     └───────┘  └─────┘
762  
763  local notation `stmt'` := stmt bool Λ' σ
id                             └──┘ └──┘
src                            └──┘ └──┘
typ                            └──┘ └──┘
doc                            └──┘
764  local notation `cfg'` := cfg bool Λ' σ
id                            └─┘ └──┘
src                           └─┘ └──┘
typ                           └─┘ └──┘
doc                           └─┘
765  
766  def read_aux : ∀ n, (vector bool n → stmt') → stmt'
id                       └────┘ └──┘   └───┘    └───┘
src                       └────┘ └──┘     └───┘    └───┘
typ                      └────┘ └──┘   └───┘    └───┘
doc                                       └───┘    └───┘
767  | 0     f := f vector.nil
id                 └────────┘
src                 └────────┘
typ                └────────┘
768  | (i+1) f := stmt.branch (λ a s, a)
id             └─────────┘       
src              └─────────┘
typ            └─────────┘       
769      (stmt.move dir.right $ read_aux i (λ v, f (tt :: v)))
id        └───────┘ └───────┘   └──────┘           └┘ └┘ 
src       └───────┘ └───────┘                       └┘ └┘
typ       └───────┘ └───────┘   └──────┘           └┘ └┘ 
770      (stmt.move dir.right $ read_aux i (λ v, f (ff :: v)))
id        └───────┘ └───────┘   └──────┘           └┘ └┘ 
src       └───────┘ └───────┘                       └┘ └┘
typ       └───────┘ └───────┘   └──────┘           └┘ └┘ 
771  
772  parameters {n : ℕ} (enc : Γ → vector bool n) (dec : vector bool n → Γ)
id                              └────┘ └──┘           └────┘ └──┘
src                               └────┘ └──┘           └────┘ └──┘
typ                             └────┘ └──┘           └────┘ └──┘
773  
774  def move (d : dir) (q : stmt') : stmt' := (stmt.move d)^[n] q
id                 └─┘       └───┘    └───┘     └───────┘  └┘ 
src                └─┘       └───┘    └───┘     └───────┘   └┘ 
typ                └─┘       └───┘    └───┘     └───────┘  └┘ 
doc                └─┘       └───┘    └───┘
775  
776  def read (f : Γ → stmt') : stmt' :=
id                    └───┘    └───┘
src                    └───┘    └───┘
typ                   └───┘    └───┘
doc                    └───┘    └───┘
777  read_aux n (λ v, move dir.left $ f (dec v))
id   └──────┘       └──┘ └──────┘     └─┘ 
src  └──────┘         └──┘ └──────┘
typ  └──────┘       └──┘ └──────┘     └─┘ 
778  
779  def write : list bool → stmt' → stmt'
id               └──┘ └──┘  └───┘   └───┘
src              └──┘ └──┘   └───┘   └───┘
typ              └──┘ └──┘  └───┘   └───┘
doc                          └───┘   └───┘
780  | []       q := q
id     └┘       
src    └┘
typ    └┘       
781  | (a :: l) q := stmt.write (λ _ _, a) $ stmt.move dir.right $ write l q
id       └┘       └────────┘            └───────┘ └───────┘   └───┘
src       └┘         └────────┘              └───────┘ └───────┘
typ      └┘       └────────┘            └───────┘ └───────┘   └───┘
782  
783  def tr_normal : stmt₁ → stmt'
id                   └───┘  └───┘
src                  └───┘   └───┘
typ                  └───┘  └───┘
doc                  └───┘   └───┘
784  | (stmt.move dir.left q)  := move dir.right $ (move dir.left)^[2] $ tr_normal q
id      └───────┘ └──────┘       └──┘ └───────┘    └──┘ └──────┘ └┘    └───────┘
src     └───────┘ └──────┘        └──┘ └───────┘    └──┘ └──────┘ └┘ 
typ     └───────┘ └──────┘       └──┘ └───────┘    └──┘ └──────┘ └┘    └───────┘
785  | (stmt.move dir.right q) := move dir.right $ tr_normal q
id      └───────┘ └───────┘      └──┘ └───────┘   └───────┘
src     └───────┘ └───────┘       └──┘ └───────┘
typ     └───────┘ └───────┘      └──┘ └───────┘   └───────┘
786  | (stmt.write f q)        := read $ λ a, stmt.goto $ λ _ s, Λ'.write (f a s) q
id      └────────┘              └──┘       └───────┘        └──────┘     
src     └────────┘                └──┘        └───────┘          └──────┘
typ     └────────┘              └──┘       └───────┘        └──────┘     
787  | (stmt.load f q)         := read $ λ a, stmt.load (λ _ s, f a s) $ tr_normal q
id      └───────┘               └──┘       └───────┘              └───────┘
src     └───────┘                 └──┘        └───────┘
typ     └───────┘               └──┘       └───────┘              └───────┘
788  | (stmt.branch p q₁ q₂)   := read $ λ a,
id      └─────────┘  └┘ └┘       └──┘     
src     └─────────┘               └──┘
typ     └─────────┘  └┘ └┘       └──┘     
789    stmt.branch (λ _ s, p a s) (tr_normal q₁) (tr_normal q₂)
id     └─────────┘             └───────┘      └───────┘
src    └─────────┘
typ    └─────────┘             └───────┘      └───────┘
790  | (stmt.goto l)           := read $ λ a,
id      └───────┘                └──┘     
src     └───────┘                 └──┘
typ     └───────┘                └──┘     
791    stmt.goto (λ _ s, Λ'.normal (l a s))
id     └───────┘       └───────┘     
src    └───────┘         └───────┘
typ    └───────┘       └───────┘     
792  | stmt.halt               := move dir.right $ move dir.left $ stmt.halt
id     └───────┘                  └──┘ └───────┘   └──┘ └──────┘   └───────┘
src    └───────┘                  └──┘ └───────┘   └──┘ └──────┘   └───────┘
typ    └───────┘                  └──┘ └───────┘   └──┘ └──────┘   └───────┘
793  
794  def tr_tape' (L R : list Γ) : tape bool :=
id                       └──┘     └──┘ └──┘
src                      └──┘      └──┘ └──┘
typ                      └──┘     └──┘ └──┘
795  tape.mk'
id   └──────┘
src  └──────┘
typ  └──────┘
796    (L.bind (λ x, (enc x).to_list.reverse))
id      └───┘       └─┘  └─────┘ └─────┘
src      └───┘              └─────┘ └─────┘
typ     └───┘       └─┘  └─────┘ └─────┘
797    (R.bind (λ x, (enc x).to_list) ++ [default _])
id      └───┘       └─┘  └─────┘   └┘ └─────┘  
src      └───┘              └─────┘   └┘ └─────┘  
typ     └───┘       └─┘  └─────┘   └┘ └─────┘  
798  
799  def tr_tape : tape Γ → tape bool
id                 └──┘   └──┘ └──┘
src                └──┘     └──┘ └──┘
typ                └──┘   └──┘ └──┘
800  | (a, L, R) := tr_tape' L (a :: R)
id              └──────┘      └┘
src                └──────┘      └┘
typ             └──────┘      └┘
801  
802  theorem tr_tape_drop_right : ∀ R : list Γ,
id                                     └──┘ 
src                                     └──┘
typ                                    └──┘ 
803    list.drop n (R.bind (λ x, (enc x).to_list)) =
id     └───────┘   └───┘       └─┘  └─────┘    
src    └───────┘     └───┘              └─────┘    
typ    └───────┘   └───┘       └─┘  └─────┘    
804    R.tail.bind (λ x, (enc x).to_list)
id     └───┘└───┘       └─┘  └─────┘
src     └───┘└───┘              └─────┘
typ    └───┘└───┘       └─┘  └─────┘
805  | []     := list.drop_nil _
id     └┘        └───────────┘
src    └┘        └───────────┘
typ    └┘        └───────────┘
806  | (a::R) := list.drop_left' (enc a).2
id      └┘      └─────────────┘  └─┘   
src      └┘      └─────────────┘        
typ     └┘      └─────────────┘  └─┘   
807  
808  parameters (enc0 : enc (default _) = vector.repeat ff n)
id                           └─────┘     └───────────┘ └┘
src                          └─────┘     └───────────┘ └┘
typ                          └─────┘     └───────────┘ └┘
809  
810  section
811  include enc0
812  theorem tr_tape_take_right : ∀ R : list Γ,
id                                     └──┘ 
src                                     └──┘
typ                                    └──┘ 
813    list.take' n (R.bind (λ x, (enc x).to_list)) =
id     └────────┘   └───┘       └─┘  └─────┘    
src    └────────┘     └───┘              └─────┘    
typ    └────────┘   └───┘       └─┘  └─────┘    
814    (enc R.head).to_list
id      └─┘ └───┘ └─────┘
src          └───┘ └─────┘
typ     └─┘ └───┘ └─────┘
815  | []     := show list.take' n list.nil = _,
id     └┘             └────────┘  └──────┘ 
src    └┘             └────────┘   └──────┘ 
typ    └┘             └────────┘  └──────┘ 
816      by rw [list.take'_nil]; exact (congr_arg vector.to_list enc0).symm
id              └────────────┘          └───────┘ └────────────┘ └──┘
src         └──┘└────────────┘  └────┘ └───────┘└────────────┘    └─────┘
typ         └──┘└────────────┘  └────┘ └───────┘└────────────┘└──┘└─────┘
doc         └──┘                └────┘                            └─────┘
txt         └──┘                └────┘                            └─────┘
par         └──┘                └────┘                            └─────┘
pid           └┘                                                 └───┘└┘
st         └─────────────────┘└───────────────────────────────────────────┘
817  | (a::R) := list.take'_left' (enc a).2
id      └┘      └──────────────┘  └─┘   
src      └┘      └──────────────┘        
typ     └┘      └──────────────┘  └─┘   
818  end
819  
820  parameters (M : Λ → stmt₁)
id                       └───┘
src                      └───┘
typ                      └───┘
doc                      └───┘
821  
822  def tr : Λ' → stmt'
id            └┘  └───┘
src           └┘   └───┘
typ           └┘  └───┘
doc                └───┘
823  | (Λ'.normal l)  := tr_normal (M l)
id      └───────┘       └───────┘  
src     └───────┘        └───────┘
typ     └───────┘       └───────┘  
824  | (Λ'.write a q) := write (enc a).to_list $ move dir.left $ tr_normal q
id      └──────┘       └───┘  └─┘   └─────┘    └──┘ └──────┘   └───────┘
src     └──────┘         └───┘        └─────┘    └──┘ └──────┘   └───────┘
typ     └──────┘       └───┘  └─┘   └─────┘    └──┘ └──────┘   └───────┘
825  
826  def tr_cfg : cfg₁ → cfg'
id                └──┘  └──┘
src               └──┘   └──┘
typ               └──┘  └──┘
doc               └──┘   └──┘
827  | ⟨l, v, T⟩ := ⟨l.map Λ'.normal, v, tr_tape T⟩
id                 └──┘ └───────┘     └─────┘
src                   └──┘ └───────┘     └─────┘
typ                └──┘ └───────┘     └─────┘
828  
829  include enc0
830  
831  theorem tr_tape'_move_left (L R) :
832    (tape.move dir.left)^[n] (tr_tape' L R) =
id      └───────┘ └──────┘ └┘  └──────┘    
src     └───────┘ └──────┘ └┘   └──────┘      
typ     └───────┘ └──────┘ └┘  └──────┘    
833    (tr_tape' L.tail (L.head :: R)) :=
id      └──────┘ └───┘  └───┘ └┘ 
src     └──────┘  └───┘   └───┘ └┘
typ     └──────┘ └───┘  └───┘ └┘ 
834  begin
st   └─────
835    cases L with a L,
id           
src    └────┘ └───────┘
typ    └────┘└───────┘
doc    └────┘ └───────┘
txt    └────┘ └───────┘
par    └────┘ └───────┘
pid          └───────┘
st   ─────────────────┘└─
836    { simp only [enc0, vector.repeat, tr_tape',
id                  └──┘  └───────────┘  └──────┘
src      └─────────┘    └┘└───────────┘└┘└──────┘└─
typ      └─────────┘└──┘└┘└───────────┘└┘└──────┘└─
doc      └─────────┘    └┘             └┘        └─
txt      └─────────┘    └┘             └┘        └─
par      └─────────┘    └┘             └┘        └─
pid          └──┘└┘    └┘             └┘        └─
st   ───┘└─────────────────────────────────────────
837        list.cons_bind, list.head, list.append_assoc],
id         └────────────┘  └───────┘  └───────────────┘
src  ─────┘└────────────┘└┘└───────┘└┘└───────────────┘
typ  ─────┘└────────────┘└┘└───────┘└┘└───────────────┘
doc  ─────┘              └┘         └┘                 
txt  ─────┘              └┘         └┘                 
par  ─────┘              └┘         └┘                 
pid  ─────┘              └┘         └┘                 
st   ──────────────────────────────────────────────────┘└─
838      suffices : ∀ i R', default _ ∈ R' →
id                          └─────┘   
src      └─────────┘ └───┘ └─────┘└─┘   
typ      └─────────┘ └───┘ └─────┘└─┘   
doc      └─────────┘ └───┘        └─┘    
txt      └─────────┘ └───┘        └─┘    
par      └─────────┘ └───┘        └─┘    
pid      └───────┘└┘ └───┘        └─┘    
st   ────────────────────────────────────────
839        (tape.move dir.left^[i]) (tape.mk' [] R') =
id          └───────┘ └──────┘└┘                    
src  ─────┘ └───────┘└──────┘└┘ └┘             └┘
typ  ─────┘ └───────┘└──────┘└┘ └┘             └┘
doc  ─────┘                      └┘             └┘ 
txt  ─────┘                      └┘             └┘ 
par  ─────┘                      └┘             └┘ 
pid  ─────┘                      └┘             └┘ 
st   ──────────────────────────────────────────────────
840        tape.mk' [] (list.repeat ff i ++ R'),
id         └──────┘ └┘  └─────────┘ └┘   └┘
src  ─────┘└──────┘└┘ └─────────┘└┘ └┘  
typ  ─────┘└──────┘└┘ └─────────┘└┘ └┘  
doc  ─────┘                             
txt  ─────┘                             
par  ─────┘                             
pid  ─────┘                             
st   ─────────────────────────────────────────┘└─
841      from this n _ (list.mem_append_right _
id            └──┘     └───────────────────┘
src      └───┘     └─┘ └───────────────────┘└──
typ      └───┘└──┘└─┘ └───────────────────┘└──
doc      └───┘     └─┘                      └──
txt      └───┘     └─┘                      └──
par      └───┘     └─┘                      └──
pid      └───┘     └─┘                      └──
st   ───────────────────────────────────────────
842        (list.mem_singleton_self _)),
id          └─────────────────────┘
src  ─────┘ └─────────────────────┘└──┘
typ  ─────┘ └─────────────────────┘└──┘
doc  ─────┘                        └──┘
txt  ─────┘                        └──┘
par  ─────┘                        └──┘
pid  ─────┘                        └──┘
st   ─────────────────────────────────┘└─
843      intros i R' hR, induction i with i IH, {refl},
id                                 
src      └────────────┘  └────────┘ └────────┘   └──┘
typ      └────────────┘  └────────┘└────────┘   └──┘
doc      └────────────┘  └────────┘ └────────┘   └──┘
txt      └────────────┘  └────────┘ └────────┘   └──┘
par      └────────────┘  └────────┘ └────────┘   └──┘
pid            └──────┘            └───────┘
st   ─────────────────┘└─────────────────────┘└─────┘└┘
844      rw [nat.iterate_succ', IH],
id           └───────────────┘  └┘
src      └──┘└───────────────┘└┘  
typ      └──┘└───────────────┘└┘└┘
doc      └──┘                 └┘  
txt      └──┘                 └┘  
par      └──┘                 └┘  
pid        └┘                 └┘  
st   ────────────────────────┘└──┘└─
845      refine prod.ext rfl (prod.ext rfl (list.cons_head_tail
id                            └──────┘ └─┘  └─────────────────┘
src      └─────┘            └──────┘└─┘ └─────────────────┘
typ      └─────┘            └──────┘└─┘ └─────────────────┘
doc      └─────┘                                           
txt      └─────┘                                           
par      └─────┘                                           
pid                                                       
st   ───────────────────────────────────────────────────────────
846        (list.ne_nil_of_mem $ list.mem_append_right _ hR))) },
id          └────────────────┘   └───────────────────┘   └┘
src  ─────┘ └────────────────┘ └───────────────────┘└─┘  └──┘
typ  ─────┘ └────────────────┘ └───────────────────┘└─┘└┘└──┘
doc  ─────┘                                         └─┘  └──┘
txt  ─────┘                                         └─┘  └──┘
par  ─────┘                                         └─┘  └──┘
pid  ─────┘                                         └─┘  └─┘
st   ─────────────────────────────────────────────────────────┘└┘
847    { simp only [tr_tape', list.cons_bind, list.append_assoc],
id                  └──────┘  └────────────┘  └───────────────┘
src      └─────────┘└──────┘└┘└────────────┘└┘└───────────────┘
typ      └─────────┘└──────┘└┘└────────────┘└┘└───────────────┘
doc      └─────────┘        └┘              └┘                 
txt      └─────────┘        └┘              └┘                 
par      └─────────┘        └┘              └┘                 
pid          └──┘└┘        └┘              └┘                 
st   ──────────────────────────────────────────────────────────┘└─
848      suffices : ∀ L' R' l₁ l₂
src      └─────────┘ └────────────
typ      └─────────┘ └────────────
doc      └─────────┘ └────────────
txt      └─────────┘ └────────────
par      └─────────┘ └────────────
pid      └───────┘└┘ └────────────
st   ─────────────────────────────
849        (hR : default _ ∈ R')
id               └─────┘   
src  ───────────┘└─────┘└─┘   └─
typ  ───────────┘└─────┘└─┘  └─
doc  ───────────┘       └─┘   └─
txt  ───────────┘       └─┘   └─
par  ───────────┘       └─┘   └─
pid  ───────────┘       └─┘   └─
st   ────────────────────────────
850        (e : vector.to_list (enc a) = list.reverse_core l₁ l₂),
id                                      └───────────────┘
src  ──────────┘                   └┘ └───────────────┘     
typ  ──────────┘                   └┘└───────────────┘     
doc  ──────────┘                   └┘                       
txt  ──────────┘                   └┘                       
par  ──────────┘                   └┘                       
pid  ──────────┘                   └┘                       
st   ──────────────────────────────────────────────────────────────
851        (tape.move dir.left^[l₁.length]) (tape.mk' (l₁ ++ L') (l₂ ++ R')) =
id          └───────┘ └──────┘    └─────┘
src  ─────┘ └───────┘└──────┘    └─────┘ └┘                └┘       └─┘ 
typ  ─────┘ └───────┘└──────┘    └─────┘ └┘                └┘       └─┘ 
doc  ─────┘                              └┘                └┘       └─┘ 
txt  ─────┘                              └┘                └┘       └─┘ 
par  ─────┘                              └┘                └┘       └─┘ 
pid  ─────┘                              └┘                └┘       └─┘ 
st   ──────────────────────────────────────────────────────────────────────────
852        tape.mk' L' (vector.to_list (enc a) ++ R'),
id         └──────┘     └────────────┘  └─┘ 
src  ─────┘└──────┘   └────────────┘     └┘    
typ  ─────┘└──────┘   └────────────┘ └─┘└┘    
doc  ─────┘                              └┘    
txt  ─────┘                              └┘    
par  ─────┘                              └┘    
pid  ─────┘                              └┘    
st   ───────────────────────────────────────────────┘└─
853      { simpa only [list.length_reverse, vector.to_list_length]
id                     └─────────────────┘  └───────────────────┘
src        └──────────┘└─────────────────┘└┘└───────────────────┘└─
typ        └──────────┘└─────────────────┘└┘└───────────────────┘└─
doc        └──────────┘                   └┘                     └─
txt        └──────────┘                   └┘                     └─
par        └──────────┘                   └┘                     └─
pid             └──┘└┘                   └┘                     
st   ─────┘└───────────────────────────────────────────────────────
854          using this _ _ _ _ _ (list.reverse_reverse _).symm,
id                 └──┘            └──────────────────┘
src  ─────────────┘    └─────────┘ └──────────────────┘└──────┘
typ  ─────────────┘└──┘└─────────┘ └──────────────────┘└──────┘
doc  ─────────────┘    └─────────┘                     └──────┘
txt  ─────────────┘    └─────────┘                     └──────┘
par  ─────────────┘    └─────────┘                     └──────┘
pid  ───────┘└────┘    └─────────┘                     └─────┘
st   ─────────────────────────────────────────────────────────┘└─
855        exact list.mem_append_right _ (list.mem_singleton_self _) },
id               └───────────────────┘    └─────────────────────┘
src        └────┘└───────────────────┘└─┘ └─────────────────────┘└──┘
typ        └────┘└───────────────────┘└─┘ └─────────────────────┘└──┘
doc        └────┘                     └─┘                        └──┘
txt        └────┘                     └─┘                        └──┘
par        └────┘                     └─┘                        └──┘
pid                                  └─┘                        └─┘
st   ───────────────────────────────────────────────────────────────┘└┘
856      intros, induction l₁ with b l₁ IH generalizing l₂,
id                         └┘
src      └────┘  └────────┘  └───────────────────────────┘
typ      └────┘  └────────┘└┘└───────────────────────────┘
doc      └────┘  └────────┘  └───────────────────────────┘
txt      └────┘  └────────┘  └───────────────────────────┘
par      └────┘  └────────┘  └───────────────────────────┘
pid                         └──────────┘└──────────────┘
st   ─────────┘└─────────────────────────────────────────┘└─
857      { cases e, refl },
id               
src        └────┘   └───┘
typ        └────┘  └───┘
doc        └────┘   └───┘
txt        └────┘   └───┘
par        └────┘   └───┘
pid                    
st   ─────┘└─────┘└─────┘└┘
858      simp only [list.length, list.cons_append, nat.iterate_succ],
id                  └─────────┘  └──────────────┘  └──────────────┘
src      └─────────┘└─────────┘└┘└──────────────┘└┘└──────────────┘
typ      └─────────┘└─────────┘└┘└──────────────┘└┘└──────────────┘
doc      └─────────┘           └┘                └┘                
txt      └─────────┘           └┘                └┘                
par      └─────────┘           └┘                └┘                
pid          └──┘└┘           └┘                └┘                
st   ──────────────────────────────────────────────────────────────┘└─
859      convert IH _ e,
id               └┘   
src      └──────┘  └─┘
typ      └──────┘└┘└─┘
doc      └──────┘  └─┘
txt      └──────┘  └─┘
par      └──────┘  └─┘
pid               └─┘
st   ─────────────────┘└─
860      exact prod.ext rfl (prod.ext rfl (list.cons_head_tail
id                           └──────┘ └─┘  └─────────────────┘
src      └────┘            └──────┘└─┘ └─────────────────┘
typ      └────┘            └──────┘└─┘ └─────────────────┘
doc      └────┘                                           
txt      └────┘                                           
par      └────┘                                           
pid                                                      
st   ──────────────────────────────────────────────────────────
861        (list.ne_nil_of_mem $ list.mem_append_right _ hR))) }
id          └────────────────┘   └───────────────────┘   └┘
src  ─────┘ └────────────────┘ └───────────────────┘└─┘  └──┘
typ  ─────┘ └────────────────┘ └───────────────────┘└─┘└┘└──┘
doc  ─────┘                                         └─┘  └──┘
txt  ─────┘                                         └─┘  └──┘
par  ─────┘                                         └─┘  └──┘
pid  ─────┘                                         └─┘  └─┘
st   ─────────────────────────────────────────────────────────┘└─
862  end
st   ──┘
863  
864  theorem tr_tape'_move_right (L R) :
865    (tape.move dir.right)^[n] (tr_tape' L R) =
id      └───────┘ └───────┘ └┘  └──────┘    
src     └───────┘ └───────┘ └┘   └──────┘      
typ     └───────┘ └───────┘ └┘  └──────┘    
866    (tr_tape' (R.head :: L) R.tail) :=
id      └──────┘  └───┘ └┘   └───┘
src     └──────┘   └───┘ └┘     └───┘
typ     └──────┘  └───┘ └┘   └───┘
867  begin
st   └─────
868    cases R with a R,
id           
src    └────┘ └───────┘
typ    └────┘└───────┘
doc    └────┘ └───────┘
txt    └────┘ └───────┘
par    └────┘ └───────┘
pid          └───────┘
st   ─────────────────┘└─
869    { simp only [enc0, vector.repeat, tr_tape', list.head,
id                  └──┘  └───────────┘  └──────┘  └───────┘
src      └─────────┘    └┘└───────────┘└┘└──────┘└┘└───────┘└─
typ      └─────────┘└──┘└┘└───────────┘└┘└──────┘└┘└───────┘└─
doc      └─────────┘    └┘             └┘        └┘         └─
txt      └─────────┘    └┘             └┘        └┘         └─
par      └─────────┘    └┘             └┘        └┘         └─
pid          └──┘└┘    └┘             └┘        └┘         └─
st   ───┘└────────────────────────────────────────────────────
870        list.cons_bind, vector.to_list_mk, list.reverse_repeat],
id         └────────────┘  └───────────────┘  └─────────────────┘
src  ─────┘└────────────┘└┘└───────────────┘└┘└─────────────────┘
typ  ─────┘└────────────┘└┘└───────────────┘└┘└─────────────────┘
doc  ─────┘              └┘                 └┘                   
txt  ─────┘              └┘                 └┘                   
par  ─────┘              └┘                 └┘                   
pid  ─────┘              └┘                 └┘                   
st   ────────────────────────────────────────────────────────────┘└─
871      suffices : ∀ i L',
src      └─────────┘ └───┘ 
typ      └─────────┘ └───┘ 
doc      └─────────┘ └───┘ 
txt      └─────────┘ └───┘ 
par      └─────────┘ └───┘ 
pid      └───────┘└┘ └───┘ 
st   ───────────────────────
872        (tape.move dir.right^[i]) (ff, L', []) =
id          └───────┘ └───────┘└┘                
src  ─────┘ └───────┘└───────┘└┘ └┘   └┘  └┘  └┘
typ  ─────┘ └───────┘└───────┘└┘ └┘   └┘  └┘  └┘
doc  ─────┘                       └┘   └┘  └┘  └┘ 
txt  ─────┘                       └┘   └┘  └┘  └┘ 
par  ─────┘                       └┘   └┘  └┘  └┘ 
pid  ─────┘                       └┘   └┘  └┘  └┘ 
st   ───────────────────────────────────────────────
873        (ff, list.repeat ff i ++ L', []),
id             └─────────┘ └┘   └┘     └┘
src  ─────┘  └┘└─────────┘└┘ └┘  └┘└┘
typ  ─────┘  └┘└─────────┘└┘ └┘  └┘└┘
doc  ─────┘   └┘                  └┘  
txt  ─────┘   └┘                  └┘  
par  ─────┘   └┘                  └┘  
pid  ─────┘   └┘                  └┘  
st   ─────────────────────────────────────┘└─
874      from this n _,
id            └──┘ 
src      └───┘     └┘
typ      └───┘└──┘└┘
doc      └───┘     └┘
txt      └───┘     └┘
par      └───┘     └┘
pid      └───┘     └┘
st   ────────────────┘└─
875      intros, induction i with i IH, {refl},
id                         
src      └────┘  └────────┘ └────────┘   └──┘
typ      └────┘  └────────┘└────────┘   └──┘
doc      └────┘  └────────┘ └────────┘   └──┘
txt      └────┘  └────────┘ └────────┘   └──┘
par      └────┘  └────────┘ └────────┘   └──┘
pid                        └───────┘
st   ─────────┘└─────────────────────┘└─────┘└┘
876      rw [nat.iterate_succ', IH],
id           └───────────────┘  └┘
src      └──┘└───────────────┘└┘  
typ      └──┘└───────────────┘└┘└┘
doc      └──┘                 └┘  
txt      └──┘                 └┘  
par      └──┘                 └┘  
pid        └┘                 └┘  
st   ────────────────────────┘└──┘└─
877      refine prod.ext rfl (prod.ext rfl rfl) },
id                            └──────┘     └─┘
src      └─────┘            └──────┘   └─┘└┘
typ      └─────┘            └──────┘   └─┘└┘
doc      └─────┘                          └┘
txt      └─────┘                          └┘
par      └─────┘                          └┘
pid                                      
st   ──────────────────────────────────────────┘└┘
878    { simp only [tr_tape', list.cons_bind, list.append_assoc],
id                  └──────┘  └────────────┘  └───────────────┘
src      └─────────┘└──────┘└┘└────────────┘└┘└───────────────┘
typ      └─────────┘└──────┘└┘└────────────┘└┘└───────────────┘
doc      └─────────┘        └┘              └┘                 
txt      └─────────┘        └┘              └┘                 
par      └─────────┘        └┘              └┘                 
pid          └──┘└┘        └┘              └┘                 
st   ──────────────────────────────────────────────────────────┘└─
879      suffices : ∀ L' R' l₁ l₂ : list bool,
id                                  └──┘ └──┘
src      └─────────┘ └─────────────┘└──┘└──┘ 
typ      └─────────┘ └─────────────┘└──┘└──┘ 
doc      └─────────┘ └─────────────┘         
txt      └─────────┘ └─────────────┘         
par      └─────────┘ └─────────────┘         
pid      └───────┘└┘ └─────────────┘         
st   ──────────────────────────────────────────
880        (tape.move dir.right^[l₂.length]) (tape.mk' (l₁ ++ L') (l₂ ++ R')) =
id          └───────┘ └───────┘    └─────┘
src  ─────┘ └───────┘└───────┘    └─────┘ └┘                └┘       └─┘ 
typ  ─────┘ └───────┘└───────┘    └─────┘ └┘                └┘       └─┘ 
doc  ─────┘                               └┘                └┘       └─┘ 
txt  ─────┘                               └┘                └┘       └─┘ 
par  ─────┘                               └┘                └┘       └─┘ 
pid  ─────┘                               └┘                └┘       └─┘ 
st   ───────────────────────────────────────────────────────────────────────────
881        tape.mk' (list.reverse_core l₂ l₁ ++ L') R',
id         └──────┘  └───────────────┘
src  ─────┘└──────┘ └───────────────┘        └┘
typ  ─────┘└──────┘ └───────────────┘        └┘
doc  ─────┘                                  └┘
txt  ─────┘                                  └┘
par  ─────┘                                  └┘
pid  ─────┘                                  └┘
st   ────────────────────────────────────────────────┘└─
882      { simpa only [vector.to_list_length] using this _ _ [] (enc a).to_list },
id                     └───────────────────┘        └──┘     └┘  └─┘ 
src        └──────────┘└───────────────────┘└──────┘    └───┘└┘     └────────┘
typ        └──────────┘└───────────────────┘└──────┘└──┘└───┘└┘ └─┘└────────┘
doc        └──────────┘                     └──────┘    └───┘       └────────┘
txt        └──────────┘                     └──────┘    └───┘       └────────┘
par        └──────────┘                     └──────┘    └───┘       └────────┘
pid             └──┘└┘                     └────┘    └───┘       └──────┘└┘
st   ─────┘└───────────────────────────────────────────────────────────────────┘└┘
883      intros, induction l₂ with b l₂ IH generalizing l₁, {refl},
id                         └┘
src      └────┘  └────────┘  └───────────────────────────┘   └──┘
typ      └────┘  └────────┘└┘└───────────────────────────┘   └──┘
doc      └────┘  └────────┘  └───────────────────────────┘   └──┘
txt      └────┘  └────────┘  └───────────────────────────┘   └──┘
par      └────┘  └────────┘  └───────────────────────────┘   └──┘
pid                         └──────────┘└──────────────┘
st   ─────────┘└─────────────────────────────────────────┘└─────┘└┘
884      exact IH (b::l₁) }
id             └┘    └┘
src      └────┘        └┘
typ      └────┘└┘   └┘└┘
doc      └────┘        └┘
txt      └────┘        └┘
par      └────┘        └┘
pid                   
st   ────────────────────┘└─
885  end
st   ──┘
886  
887  theorem step_aux_move (d q v T) :
888    step_aux (move d q) v T =
id     └──────┘  └──┘      
src    └──────┘  └──┘          
typ    └──────┘  └──┘      
doc    └──────┘
889    step_aux q v ((tape.move d)^[n] T) :=
id     └──────┘     └───────┘  └┘ 
src    └──────┘       └───────┘   └┘ 
typ    └──────┘     └───────┘  └┘ 
doc    └──────┘
890  begin
st   └─────
891    suffices : ∀ i,
src    └─────────┘ └┘ 
typ    └─────────┘ └┘ 
doc    └─────────┘ └┘ 
txt    └─────────┘ └┘ 
par    └─────────┘ └┘ 
pid    └───────┘└┘ └┘ 
st   ──────────────────
892      step_aux (stmt.move d^[i] q) v T =
id                 └───────┘  └┘         
src  ───┘         └───────┘ └┘  └┘  
typ  ───┘         └───────┘ └┘  └┘  
doc  ───┘                        └┘   
txt  ───┘                        └┘   
par  ───┘                        └┘   
pid  ───┘                        └┘   
st   ───────────────────────────────────────
893      step_aux q v (tape.move d^[i] T), from this n,
id       └──────┘    └───────┘              └──┘ 
src  ───┘└──────┘   └───────┘        └───┘    
typ  ───┘└──────┘ └───────┘      └───┘└──┘
doc  ───┘└──────┘                    └───┘    
txt  ───┘                            └───┘    
par  ───┘                            └───┘    
pid  ───┘                            └───┘    
st   ───────────────────────────────────┘└───────────┘└─
894    intro, induction i with i IH generalizing T, {refl},
id                      
src    └───┘  └────────┘ └───────────────────────┘   └──┘
typ    └───┘  └────────┘└───────────────────────┘   └──┘
doc    └───┘  └────────┘ └───────────────────────┘   └──┘
txt    └───┘  └────────┘ └───────────────────────┘   └──┘
par    └───┘  └────────┘ └───────────────────────┘   └──┘
pid                     └───────┘└─────────────┘
st   ──────┘└────────────────────────────────────┘└─────┘└┘
895    rw [nat.iterate_succ', step_aux, IH, ← nat.iterate_succ]
id         └───────────────┘  └──────┘  └┘    └──────────────┘
src    └──┘└───────────────┘└┘└──────┘└┘  └──┘└──────────────┘└┘
typ    └──┘└───────────────┘└┘└──────┘└┘└┘└──┘└──────────────┘└┘
doc    └──┘                 └┘└──────┘└┘  └──┘                └┘
txt    └──┘                 └┘        └┘  └──┘                └┘
par    └──┘                 └┘        └┘  └──┘                └┘
pid      └┘                 └┘        └┘  └──┘                
st   ──────────────────────┘└────────┘└──┘└──────────────────┘
896  end
st   └─┘
897  
898  parameters (encdec : ∀ a, dec (enc a) = a)
id                                        
src                                        
typ                                       
899  include encdec
900  
901  theorem step_aux_read (f v L R) :
902    step_aux (read f) v (tr_tape' L R) =
id     └──────┘  └──┘     └──────┘    
src    └──────┘  └──┘       └──────┘      
typ    └──────┘  └──┘     └──────┘    
doc    └──────┘
903    step_aux (f R.head) v (tr_tape' L (R.head :: R.tail)) :=
id     └──────┘   └───┘    └──────┘   └───┘ └┘ └───┘
src    └──────┘     └───┘     └──────┘     └───┘ └┘  └───┘
typ    └──────┘   └───┘    └──────┘   └───┘ └┘ └───┘
doc    └──────┘
904  begin
st   └─────
905    suffices : ∀ f,
src    └─────────┘ └┘ 
typ    └─────────┘ └┘ 
doc    └─────────┘ └┘ 
txt    └─────────┘ └┘ 
par    └─────────┘ └┘ 
pid    └───────┘└┘ └┘ 
st   ──────────────────
906      step_aux (read_aux n f) v (tr_tape' enc L R) =
id                 └──────┘                          
src  ───┘         └──────┘  └┘               └┘
typ  ───┘         └──────┘ └┘               └┘
doc  ───┘                   └┘               └┘ 
txt  ───┘                   └┘               └┘ 
par  ───┘                   └┘               └┘ 
pid  ───┘                   └┘               └┘ 
st   ───────────────────────────────────────────────────
907      step_aux (f (enc R.head)) v
id       └──────┘                  
src  ───┘└──────┘            └─┘ 
typ  ───┘└──────┘            └─┘
doc  ───┘└──────┘            └─┘ 
txt  ───┘                    └─┘ 
par  ───┘                    └─┘ 
pid  ───┘                    └─┘ 
st   ────────────────────────────────
908        (tr_tape' enc (R.head :: L) R.tail),
id          └──────┘ └─┘  └────┘ └┘   └────┘
src  ─────┘ └──────┘    └────┘└┘ └┘└────┘
typ  ─────┘ └──────┘└─┘ └────┘└┘└┘└────┘
doc  ─────┘                      └┘      
txt  ─────┘                      └┘      
par  ─────┘                      └┘      
pid  ─────┘                      └┘      
st   ────────────────────────────────────────┘└─
909    { rw [read, this, step_aux_move enc enc0, encdec,
id           └──┘  └──┘  └───────────┘ └─┘ └──┘  └────┘
src      └──┘└──┘└┘    └┘└───────────┘       └┘      └─
typ      └──┘└──┘└┘└──┘└┘└───────────┘└─┘└──┘└┘└────┘└─
doc      └──┘    └┘    └┘                    └┘      └─
txt      └──┘    └┘    └┘                    └┘      └─
par      └──┘    └┘    └┘                    └┘      └─
pid        └┘    └┘    └┘                    └┘      └─
st   ───┘└──────┘└────┘└──────────────────────┘└──────┘└─
910        tr_tape'_move_left enc enc0], refl },
id         └────────────────┘ └─┘ └──┘
src  ─────┘└────────────────┘         └───┘
typ  ─────┘└────────────────┘└─┘└──┘  └───┘
doc  ─────┘                           └───┘
txt  ─────┘                           └───┘
par  ─────┘                           └───┘
pid  ─────┘                               
st   ────────────────────────────────┘└──────┘└┘
911    cases R with a R,
id           
src    └────┘ └───────┘
typ    └────┘└───────┘
doc    └────┘ └───────┘
txt    └────┘ └───────┘
par    └────┘ └───────┘
pid          └───────┘
st   ─────────────────┘└─
912    { suffices : ∀ i f L',
src      └─────────┘ └─────┘ 
typ      └─────────┘ └─────┘ 
doc      └─────────┘ └─────┘ 
txt      └─────────┘ └─────┘ 
par      └─────────┘ └─────┘ 
pid      └───────┘└┘ └─────┘ 
st   ───┘└────────────────────
913        step_aux (read_aux i f) v (ff, L', []) =
id                   └──────┘
src  ─────┘         └──────┘  └┘    └┘  └┘  └┘ 
typ  ─────┘         └──────┘  └┘    └┘  └┘  └┘ 
doc  ─────┘                   └┘    └┘  └┘  └┘ 
txt  ─────┘                   └┘    └┘  └┘  └┘ 
par  ─────┘                   └┘    └┘  └┘  └┘ 
pid  ─────┘                   └┘    └┘  └┘  └┘ 
st   ───────────────────────────────────────────────
914        step_aux (f (vector.repeat ff i)) v
id         └──────┘     └───────────┘        
src  ─────┘└──────┘   └───────────┘   └─┘ 
typ  ─────┘└──────┘   └───────────┘   └─┘
doc  ─────┘└──────┘                   └─┘ 
txt  ─────┘                           └─┘ 
par  ─────┘                           └─┘ 
pid  ─────┘                           └─┘ 
st   ──────────────────────────────────────────
915          (ff, list.repeat ff i ++ L', []),
id               └─────────┘ └┘   └┘     └┘
src  ───────┘  └┘└─────────┘└┘ └┘  └┘└┘
typ  ───────┘  └┘└─────────┘└┘ └┘  └┘└┘
doc  ───────┘   └┘                  └┘  
txt  ───────┘   └┘                  └┘  
par  ───────┘   └┘                  └┘  
pid  ───────┘   └┘                  └┘  
st   ───────────────────────────────────────┘└─
916      { intro f, convert this n f _,
id                          └──┘  
src        └─────┘  └──────┘      └┘
typ        └─────┘  └──────┘└──┘└┘
doc        └─────┘  └──────┘      └┘
txt        └─────┘  └──────┘      └┘
par        └─────┘  └──────┘      └┘
pid             └┘               └┘
st   ─────┘└─────┘└──────────────────┘└─
917        refine prod.ext rfl (prod.ext ((list.cons_bind _ _ _).trans _) rfl),
id                              └──────┘   └────────────┘                 └─┘
src        └─────┘            └──────┘  └────────────┘└───────────────┘└─┘
typ        └─────┘            └──────┘  └────────────┘└───────────────┘└─┘
doc        └─────┘                                    └───────────────┘   
txt        └─────┘                                    └───────────────┘   
par        └─────┘                                    └───────────────┘   
pid                                                  └───────────────┘   
st   ────────────────────────────────────────────────────────────────────────┘└─
918        simp only [list.head, enc0, vector.repeat, vector.to_list, list.reverse_repeat] },
id                    └───────┘  └──┘  └───────────┘  └────────────┘  └─────────────────┘
src        └─────────┘└───────┘└┘    └┘└───────────┘└┘└────────────┘└┘└─────────────────┘└┘
typ        └─────────┘└───────┘└┘└──┘└┘└───────────┘└┘└────────────┘└┘└─────────────────┘└┘
doc        └─────────┘         └┘    └┘             └┘              └┘                   └┘
txt        └─────────┘         └┘    └┘             └┘              └┘                   └┘
par        └─────────┘         └┘    └┘             └┘              └┘                   └┘
pid            └──┘└┘         └┘    └┘             └┘              └┘                   
st   ─────────────────────────────────────────────────────────────────────────────────────┘└┘
919      clear f L, intros, induction i with i IH generalizing L', {refl},
id                                    
src      └───────┘  └────┘  └────────┘ └────────────────────────┘   └──┘
typ      └───────┘  └────┘  └────────┘└────────────────────────┘   └──┘
doc      └───────┘  └────┘  └────────┘ └────────────────────────┘   └──┘
txt      └───────┘  └────┘  └────────┘ └────────────────────────┘   └──┘
par      └───────┘  └────┘  └────────┘ └────────────────────────┘   └──┘
pid           └──┘                    └───────┘└──────────────┘
st   ────────────┘└──────┘└─────────────────────────────────────┘└─────┘└┘
920      change step_aux (read_aux i (λ v, f (ff :: v))) v (ff, ff :: L', [])
id                        └──────┘
src      └─────┘         └──────┘   └──┘       └──┘    └┘      └┘  └─
typ      └─────┘         └──────┘   └──┘       └──┘    └┘      └┘  └─
doc      └─────┘                    └──┘       └──┘    └┘      └┘  └─
txt      └─────┘                    └──┘       └──┘    └┘      └┘  └─
par      └─────┘                    └──┘       └──┘    └┘      └┘  └─
pid                                └──┘       └──┘    └┘      └┘  └─
st   ─────────────────────────────────────────────────────────────────────────
921        = step_aux (f (vector.repeat ff (nat.succ i))) v (ff, ff :: (list.repeat ff i ++ L'), []),
id           └──────┘    └───────────┘     └──────┘                  └─────────┘ └┘     └┘   └┘
src  ─────┘ └──────┘   └───────────┘   └──────┘ └──┘   └┘     └─────────┘└┘     └─┘└┘
typ  ─────┘ └──────┘  └───────────┘   └──────┘ └──┘  └┘     └─────────┘└┘  └┘└─┘└┘
doc  ─────┘ └──────┘                            └──┘    └┘                       └─┘  
txt  ─────┘                                     └──┘    └┘                       └─┘  
par  ─────┘                                     └──┘    └┘                       └─┘  
pid  ─────┘                                     └──┘    └┘                       └─┘  
st   ──────────────────────────────────────────────────────────────────────────────────────────────┘└─
922      rw [IH], congr',
id           └┘
src      └──┘    └────┘
typ      └──┘└┘  └────┘
doc      └──┘    └────┘
txt      └──┘    └────┘
par      └──┘    └────┘
pid        └┘  
st   ─────────┘└───────┘└─
923      simpa only [list.append_assoc] using congr_arg (++ L') (list.repeat_add ff i 1).symm },
id                   └───────────────┘        └───────┘    └┘   └─────────────┘ └┘ 
src      └──────────┘└───────────────┘└──────┘└───────┘└─┘  └┘ └─────────────┘└┘ └───────┘
typ      └──────────┘└───────────────┘└──────┘└───────┘└─┘└┘└┘ └─────────────┘└┘└───────┘
doc      └──────────┘                 └──────┘          └─┘  └┘                   └───────┘
txt      └──────────┘                 └──────┘          └─┘  └┘                   └───────┘
par      └──────────┘                 └──────┘          └─┘  └┘                   └───────┘
pid           └──┘└┘                 └────┘          └─┘  └┘                   └─────┘└┘
st   ────────────────────────────────────────────────────────────────────────────────────────┘└┘
924    { simp only [tr_tape', list.cons_bind, list.append_assoc],
id                  └──────┘  └────────────┘  └───────────────┘
src      └─────────┘└──────┘└┘└────────────┘└┘└───────────────┘
typ      └─────────┘└──────┘└┘└────────────┘└┘└───────────────┘
doc      └─────────┘        └┘              └┘                 
txt      └─────────┘        └┘              └┘                 
par      └─────────┘        └┘              └┘                 
pid          └──┘└┘        └┘              └┘                 
st   ──────────────────────────────────────────────────────────┘└─
925      suffices : ∀ i f L' R' l₁ l₂ h,
src      └─────────┘ └────────────────┘ 
typ      └─────────┘ └────────────────┘ 
doc      └─────────┘ └────────────────┘ 
txt      └─────────┘ └────────────────┘ 
par      └─────────┘ └────────────────┘ 
pid      └───────┘└┘ └────────────────┘ 
st   ────────────────────────────────────
926        step_aux (read_aux i f) v
id                   └──────┘
src  ─────┘         └──────┘  └┘ 
typ  ─────┘         └──────┘  └┘ 
doc  ─────┘                   └┘ 
txt  ─────┘                   └┘ 
par  ─────┘                   └┘ 
pid  ─────┘                   └┘ 
st   ────────────────────────────────
927          (tape.mk' (l₁ ++ L') (l₂ ++ R')) =
src  ───────┘                └┘       └─┘ 
typ  ───────┘                └┘       └─┘ 
doc  ───────┘                └┘       └─┘ 
txt  ───────┘                └┘       └─┘ 
par  ───────┘                └┘       └─┘ 
pid  ───────┘                └┘       └─┘ 
st   ───────────────────────────────────────────
928        step_aux (f ⟨l₂, h⟩) v
id         └──────┘             
src  ─────┘└──────┘     └┘ └─┘ 
typ  ─────┘└──────┘     └┘ └─┘
doc  ─────┘└──────┘     └┘ └─┘ 
txt  ─────┘             └┘ └─┘ 
par  ─────┘             └┘ └─┘ 
pid  ─────┘             └┘ └─┘ 
st   ─────────────────────────────
929          (tape.mk' (l₂.reverse_core l₁ ++ L') R'),
id            └──────┘    └───────────┘
src  ───────┘ └──────┘   └───────────┘      └┘  
typ  ───────┘ └──────┘   └───────────┘      └┘  
doc  ───────┘                               └┘  
txt  ───────┘                               └┘  
par  ───────┘                               └┘  
pid  ───────┘                               └┘  
st   ───────────────────────────────────────────────┘└─
930      { intro f, convert this n f _ _ _ _ (enc a).2;
id                          └──┘            └─┘ 
src        └─────┘  └──────┘      └───────┘     └─┘
typ        └─────┘  └──────┘└──┘└───────┘ └─┘└─┘
doc        └─────┘  └──────┘      └───────┘     └─┘
txt        └─────┘  └──────┘      └───────┘     └─┘
par        └─────┘  └──────┘      └───────┘     └─┘
pid             └┘               └───────┘     └┘
st   ─────┘└─────┘└─────────────────────────────────────
931          simp only [subtype.eta]; refl },
id                      └─────────┘
src          └─────────┘└─────────┘  └───┘
typ          └─────────┘└─────────┘  └───┘
doc          └─────────┘             └───┘
txt          └─────────┘             └───┘
par          └─────────┘             └───┘
pid              └──┘└┘                 
st   ─────────────────────────────────────┘└┘
932      clear f L a R, intros, subst i,
id                                    
src      └───────────┘  └────┘  └────┘
typ      └───────────┘  └────┘  └────┘
doc      └───────────┘  └────┘  └────┘
txt      └───────────┘  └────┘  └────┘
par      └───────────┘  └────┘  └────┘
pid           └──────┘               
st   ────────────────┘└──────┘└───────┘└─
933      induction l₂ with a l₂ IH generalizing l₁, {refl},
id                 └┘
src      └────────┘  └───────────────────────────┘   └──┘
typ      └────────┘└┘└───────────────────────────┘   └──┘
doc      └────────┘  └───────────────────────────┘   └──┘
txt      └────────┘  └───────────────────────────┘   └──┘
par      └────────┘  └───────────────────────────┘   └──┘
pid                 └──────────┘└──────────────┘
st   ────────────────────────────────────────────┘└─────┘└┘
934      change (tape.mk' (l₁ ++ L') (a :: (l₂ ++ R'))).1 with a,
id               └──────┘  └┘    └┘        └┘    └┘           
src      └─────┘ └──────┘       └┘           └─────────┘
typ      └─────┘ └──────┘ └┘  └┘└┘    └┘  └┘└─────────┘
doc      └─────┘                └┘           └─────────┘
txt      └─────┘                └┘           └─────────┘
par      └─────┘                └┘           └─────────┘
pid                            └┘           └─┘└──────┘
st   ─────────────────────────────────────────────────────────────
935      transitivity step_aux
id                    └──────┘
src      └───────────┘└──────┘
typ      └───────────┘└──────┘
doc      └───────────┘└──────┘
txt      └───────────┘        
par      └───────────┘        
pid                          
st   ──────────────────────────
936        (read_aux l₂.length (λ v, f (a :: v))) v
id          └──────┘ └───────┘                   
src  ─────┘ └──────┘└───────┘  └──┘      └──┘ 
typ  ─────┘ └──────┘└───────┘  └──┘     └──┘
doc  ─────┘                    └──┘      └──┘ 
txt  ─────┘                    └──┘      └──┘ 
par  ─────┘                    └──┘      └──┘ 
pid  ─────┘                    └──┘      └──┘ 
st   ───────────────────────────────────────────────
937        (tape.mk' (a :: l₁ ++ L') (l₂ ++ R')),
id          └──────┘      └┘    └┘   └┘    └┘
src  ─────┘ └──────┘          └┘       └┘
typ  ─────┘ └──────┘   └┘  └┘└┘ └┘  └┘└┘
doc  ─────┘                   └┘       └┘
txt  ─────┘                   └┘       └┘
par  ─────┘                   └┘       └┘
pid  ─────┘                   └┘       └┘
st   ──────────────────────────────────────────┘└─
938      { cases a; refl },
id               
src        └────┘   └───┘
typ        └────┘  └───┘
doc        └────┘   └───┘
txt        └────┘   └───┘
par        └────┘   └───┘
pid                    
st   ─────┘└────────────┘└┘
939      rw IH, refl }
id          └┘
src      └─┘    └───┘
typ      └─┘└┘  └───┘
doc      └─┘    └───┘
txt      └─┘    └───┘
par      └─┘    └───┘
pid                
st   ────────┘└─────┘└─
940  end
st   ──┘
941  
942  theorem step_aux_write (q v a b L R) :
943    step_aux (write (enc a).to_list q) v (tr_tape' L (b :: R)) =
id     └──────┘  └───┘  └─┘  └─────┘      └──────┘    └┘    
src    └──────┘  └───┘        └─────┘        └──────┘      └┘     
typ    └──────┘  └───┘  └─┘  └─────┘      └──────┘    └┘    
doc    └──────┘
944    step_aux q v (tr_tape' (a :: L) R) :=
id     └──────┘    └──────┘   └┘   
src    └──────┘      └──────┘    └┘
typ    └──────┘    └──────┘   └┘   
doc    └──────┘
945  begin
st   └─────
946    simp only [tr_tape', list.cons_bind, list.append_assoc],
id                └──────┘  └────────────┘  └───────────────┘
src    └─────────┘└──────┘└┘└────────────┘└┘└───────────────┘
typ    └─────────┘└──────┘└┘└────────────┘└┘└───────────────┘
doc    └─────────┘        └┘              └┘                 
txt    └─────────┘        └┘              └┘                 
par    └─────────┘        └┘              └┘                 
pid        └──┘└┘        └┘              └┘                 
st   ────────────────────────────────────────────────────────┘└─
947    suffices : ∀ {L' R'} (l₁ l₂ l₂' : list bool)
id                                       └──┘ └──┘
src    └─────────┘ └────────────────────┘└──┘└──┘└─
typ    └─────────┘ └────────────────────┘└──┘└──┘└─
doc    └─────────┘ └────────────────────┘        └─
txt    └─────────┘ └────────────────────┘        └─
par    └─────────┘ └────────────────────┘        └─
pid    └───────┘└┘ └────────────────────┘        └─
st   ───────────────────────────────────────────────
948      (e : l₂'.length = l₂.length),
id               └─────┘    └─────┘
src  ────────┘   └─────┘  └─────┘ 
typ  ────────┘   └─────┘  └─────┘ 
doc  ────────┘                     
txt  ────────┘                     
par  ────────┘                     
pid  ────────┘                     
st   ──────────────────────────────────
949      step_aux (write l₂ q) v (tape.mk' (l₁ ++ L') (l₂' ++ R')) =
id                 └───┘                       └┘
src  ───┘         └───┘   └┘             └┘  └┘        └─┘ 
typ  ───┘         └───┘   └┘             └┘  └┘        └─┘ 
doc  ───┘                 └┘                 └┘        └─┘ 
txt  ───┘                 └┘                 └┘        └─┘ 
par  ───┘                 └┘                 └┘        └─┘ 
pid  ───┘                 └┘                 └┘        └─┘ 
st   ────────────────────────────────────────────────────────────────
950      step_aux q v (tape.mk' (list.reverse_core l₂ l₁ ++ L') R'),
id       └──────┘    └──────┘  └───────────────┘
src  ───┘└──────┘   └──────┘ └───────────────┘        └┘  
typ  ───┘└──────┘ └──────┘ └───────────────┘        └┘  
doc  ───┘└──────┘                                     └┘  
txt  ───┘                                             └┘  
par  ───┘                                             └┘  
pid  ───┘                                             └┘  
st   ─────────────────────────────────────────────────────────────┘└─
951    from this [] _ _ ((enc b).2.trans (enc a).2.symm),
id          └──┘                         └─┘ 
src    └───┘      └───┘      └────────┘     └───────┘
typ    └───┘└──┘  └───┘     └────────┘ └─┘└───────┘
doc    └───┘      └───┘      └────────┘     └───────┘
txt    └───┘      └───┘      └────────┘     └───────┘
par    └───┘      └───┘      └────────┘     └───────┘
pid    └───┘      └───┘      └────────┘     └───────┘
st   ──────────────────────────────────────────────────┘└─
952    clear a b L R, intros,
src    └───────────┘  └────┘
typ    └───────────┘  └────┘
doc    └───────────┘  └────┘
txt    └───────────┘  └────┘
par    └───────────┘  └────┘
pid         └──────┘
st   ──────────────┘└──────┘└─
953    induction l₂ with a l₂ IH generalizing l₁ l₂',
id               └┘
src    └────────┘  └───────────────────────────────┘
typ    └────────┘└┘└───────────────────────────────┘
doc    └────────┘  └───────────────────────────────┘
txt    └────────┘  └───────────────────────────────┘
par    └────────┘  └───────────────────────────────┘
pid               └──────────┘└──────────────────┘
st   ──────────────────────────────────────────────┘└─
954    { cases list.length_eq_zero.1 e, refl },
id             └─────────────────┘   
src      └────┘└─────────────────┘└─┘   └───┘
typ      └────┘└─────────────────┘└─┘  └───┘
doc      └────┘                   └─┘   └───┘
txt      └────┘                   └─┘   └───┘
par      └────┘                   └─┘   └───┘
pid                              └─┘       
st   ───┘└───────────────────────────┘└─────┘└┘
955    cases l₂' with b l₂'; injection e with e,
id           └─┘                       
src    └────┘   └─────────┘  └────────┘ └─────┘
typ    └────┘└─┘└─────────┘  └────────┘└─────┘
doc    └────┘   └─────────┘  └────────┘ └─────┘
txt    └────┘   └─────────┘  └────────┘ └─────┘
par    └────┘   └─────────┘  └────────┘ └─────┘
pid            └─────────┘            └─────┘
st   ─────────────────────────────────────────┘└─
956    unfold write step_aux,
src    └───────────────────┘
typ    └───────────────────┘
doc    └───────────────────┘
txt    └───────────────────┘
par    └───────────────────┘
pid          └─────────────┘
st   ──────────────────────┘└─
957    convert IH _ _ e, refl
id             └┘     
src    └──────┘  └───┘   └───┘
typ    └──────┘└┘└───┘  └───┘
doc    └──────┘  └───┘   └───┘
txt    └──────┘  └───┘   └───┘
par    └──────┘  └───┘   └───┘
pid             └───┘       
st   ─────────────────┘└─────┘
958  end
st   └─┘
959  
960  theorem tr_respects : respects (step M) (step tr)
id                         └──────┘  └──┘    └──┘ └┘
src                        └──────┘  └──┘     └──┘ └┘
typ                        └──────┘  └──┘    └──┘ └┘
961    (λ c₁ c₂, tr_cfg c₁ = c₂) :=
id        └┘ └┘  └────┘ └┘  └┘
src              └────┘    
typ       └┘ └┘  └────┘ └┘  └┘
962  fun_respects.2 $ λ ⟨l₁, v, (a, L, R)⟩, begin
id   └──────────┘             
src  └──────────┘              
typ  └──────────┘             
st                                          └─────
963    cases l₁ with l₁, {exact rfl},
id           └┘                 └─┘
src    └────┘  └──────┘   └────┘└─┘
typ    └────┘└┘└──────┘   └────┘└─┘
doc    └────┘  └──────┘   └────┘
txt    └────┘  └──────┘   └────┘
par    └────┘  └──────┘   └────┘
pid           └──────┘        
st   ─────────────────┘└──────────┘└┘
964    suffices : ∀ q R, reaches (step (tr enc dec M))
id                       └─────┘  └──┘  └┘         
src    └─────────┘ └──┘ └─────┘ └──┘ └┘       └──
typ    └─────────┘ └──┘ └─────┘ └──┘ └┘      └──
doc    └─────────┘ └──┘                       └──
txt    └─────────┘ └──┘                       └──
par    └─────────┘ └──┘                       └──
pid    └───────┘└┘ └──┘                       └──
st   ──────────────────────────────────────────────────
965      (step_aux (tr_normal dec q) v (tr_tape' enc L R))
id                  └───────┘ └─┘       └──────┘
src  ───┘          └───────┘    └┘  └──────┘     └──
typ  ───┘          └───────┘└─┘ └┘  └──────┘     └──
doc  ───┘                       └┘               └──
txt  ───┘                       └┘               └──
par  ───┘                       └┘               └──
pid  ───┘                       └┘               └──
st   ──────────────────────────────────────────────────────
966      (tr_cfg enc (step_aux q v (tape.mk' L R))),
id        └────┘ └─┘  └──────┘     └──────┘ 
src  ───┘ └────┘    └──────┘   └──────┘  └─┘
typ  ───┘ └────┘└─┘ └──────┘  └──────┘ └─┘
doc  ───┘           └──────┘             └─┘
txt  ───┘                                └─┘
par  ───┘                                └─┘
pid  ───┘                                └─┘
st   ─────────────────────────────────────────────┘└─
967    { refine trans_gen.head' rfl (this _ (a::R)) },
id              └─────────────┘ └─┘  └──┘      
src      └─────┘└─────────────┘└─┘     └─┘     └─┘
typ      └─────┘└─────────────┘└─┘ └──┘└─┘   └─┘
doc      └─────┘                       └─┘     └─┘
txt      └─────┘                       └─┘     └─┘
par      └─────┘                       └─┘     └─┘
pid                                   └─┘     └┘
st   ───┘└─────────────────────────────────────────┘└┘
968    clear R l₁, intros,
src    └────────┘  └────┘
typ    └────────┘  └────┘
doc    └────────┘  └────┘
txt    └────────┘  └────┘
par    └────────┘  └────┘
pid         └───┘
st   ───────────┘└──────┘└─
969    induction q with _ q IH _ q IH _ q IH generalizing v L R,
id               
src    └────────┘ └───────────────────────────────────────────┘
typ    └────────┘└───────────────────────────────────────────┘
doc    └────────┘ └───────────────────────────────────────────┘
txt    └────────┘ └───────────────────────────────────────────┘
par    └────────┘ └───────────────────────────────────────────┘
pid              └───────────────────────┘└─────────────────┘
st   ─────────────────────────────────────────────────────────┘└─
970    case TM1.stmt.move : d q IH {
src    └─────────────────────────────
typ    └─────────────────────────────
doc    └─────────────────────────────
txt    └─────────────────────────────
par    └─────────────────────────────
pid        └────────────┘└───────┘└──
st   ──────────────────────────────┘
971      cases d; simp only [tr_normal, nat.iterate, step_aux_move enc enc0, step_aux,
id                          └───────┘  └─────────┘  └───────────┘ └─┘ └──┘  └──────┘
src  ───┘└────┘ └┘└─────────┘└───────┘└┘└─────────┘└┘└───────────┘       └┘└──────┘└─
typ  ───┘└────┘└┘└─────────┘└───────┘└┘└─────────┘└┘└───────────┘└─┘└──┘└┘└──────┘└─
doc  ───┘└────┘ └┘└─────────┘         └┘           └┘                    └┘└──────┘└─
txt  ───┘└────┘ └┘└─────────┘         └┘           └┘                    └┘        └─
par  ───┘└────┘ └┘└─────────┘         └┘           └┘                    └┘        └─
pid  ─────────┘ └───────────┘         └┘           └┘                    └┘        └─
st   ──────────────────────────────────────────────────────────────────────────────────
972        tr_tape'_move_left enc enc0, tr_tape'_move_right enc enc0];
id         └────────────────┘ └─┘ └──┘  └─────────────────┘ └─┘ └──┘
src  ─────┘└────────────────┘       └┘└─────────────────┘       └─
typ  ─────┘└────────────────┘└─┘└──┘└┘└─────────────────┘└─┘└──┘└─
doc  ─────┘                         └┘                          └─
txt  ─────┘                         └┘                          └─
par  ─────┘                         └┘                          └─
pid  ─────┘                         └┘                          └──
st   ──────────────────────────────────────────────────────────────────
973        apply IH },
src  ─────┘└────┘  
typ  ─────┘└────┘  
doc  ─────┘└────┘  
txt  ─────┘└────┘  
par  ─────┘└────┘  
pid  ───────────┘  └┘
st   ──────────────┘└┘
974    case TM1.stmt.write : a q IH {
src    └──────────────────────────────
typ    └──────────────────────────────
doc    └──────────────────────────────
txt    └──────────────────────────────
par    └──────────────────────────────
pid        └─────────────┘└───────┘└──
st   ───────────────────────────────┘
975      simp only [tr_normal, step_aux_read enc dec enc0 encdec, step_aux],
id                  └───────┘  └───────────┘ └─┘ └─┘ └──┘ └────┘  └──────┘
src  ───┘└─────────┘└───────┘└┘└───────────┘                └┘└──────┘└─
typ  ───┘└─────────┘└───────┘└┘└───────────┘└─┘└─┘└──┘└────┘└┘└──────┘└─
doc  ───┘└─────────┘         └┘                             └┘└──────┘└─
txt  ───┘└─────────┘         └┘                             └┘        └─
par  ───┘└─────────┘         └┘                             └┘        └─
pid  ──────────────┘         └┘                             └┘        └──
st   ─────────────────────────────────────────────────────────────────────┘└─
976      refine refl_trans_gen.head rfl _,
id              └─────────────────┘ └─┘
src  ───┘└─────┘└─────────────────┘└─┘└┘└─
typ  ───┘└─────┘└─────────────────┘└─┘└┘└─
doc  ───┘└─────┘                      └┘└─
txt  ───┘└─────┘                      └┘└─
par  ───┘└─────┘                      └┘└─
pid  ──────────┘                      └───
st   ───────────────────────────────────┘└─
977      simp only [tr, tr_normal, step_aux,
id                  └┘  └───────┘  └──────┘
src  ───┘└─────────┘└┘└┘└───────┘└┘└──────┘└─
typ  ───┘└─────────┘└┘└┘└───────┘└┘└──────┘└─
doc  ───┘└─────────┘  └┘         └┘└──────┘└─
txt  ───┘└─────────┘  └┘         └┘        └─
par  ───┘└─────────┘  └┘         └┘        └─
pid  ──────────────┘  └┘         └┘        └─
st   ────────────────────────────────────────
978        step_aux_write enc dec enc0 encdec,
id         └────────────┘ └─┘ └─┘ └──┘ └────┘
src  ─────┘└────────────┘                └─
typ  ─────┘└────────────┘└─┘└─┘└──┘└────┘└─
doc  ─────┘                              └─
txt  ─────┘                              └─
par  ─────┘                              └─
pid  ─────┘                              └─
st   ──────────────────────────────────────────
979        step_aux_move enc enc0, tr_tape'_move_left enc enc0],
id         └───────────┘ └─┘ └──┘  └────────────────┘ └─┘ └──┘
src  ─────┘└───────────┘       └┘└────────────────┘       └─
typ  ─────┘└───────────┘└─┘└──┘└┘└────────────────┘└─┘└──┘└─
doc  ─────┘                    └┘                         └─
txt  ─────┘                    └┘                         └─
par  ─────┘                    └┘                         └─
pid  ─────┘                    └┘                         └──
st   ─────────────────────────────────────────────────────────┘└─
980      apply IH },
src  ───┘└────┘  
typ  ───┘└────┘  
doc  ───┘└────┘  
txt  ───┘└────┘  
par  ───┘└────┘  
pid  ─────────┘  └┘
st   ────────────┘└┘
981    case TM1.stmt.load : a q IH {
src    └─────────────────────────────
typ    └─────────────────────────────
doc    └─────────────────────────────
txt    └─────────────────────────────
par    └─────────────────────────────
pid        └────────────┘└───────┘└──
st   ──────────────────────────────┘
982      simp only [tr_normal, step_aux_read enc dec enc0 encdec],
id                  └───────┘  └───────────┘ └─┘ └─┘ └──┘ └────┘
src  ───┘└─────────┘└───────┘└┘└───────────┘                └─
typ  ───┘└─────────┘└───────┘└┘└───────────┘└─┘└─┘└──┘└────┘└─
doc  ───┘└─────────┘         └┘                             └─
txt  ───┘└─────────┘         └┘                             └─
par  ───┘└─────────┘         └┘                             └─
pid  ──────────────┘         └┘                             └──
st   ───────────────────────────────────────────────────────────┘└─
983      apply IH },
src  ───┘└────┘  
typ  ───┘└────┘  
doc  ───┘└────┘  
txt  ───┘└────┘  
par  ───┘└────┘  
pid  ─────────┘  └┘
st   ────────────┘└┘
984    case TM1.stmt.branch : p q₁ q₂ IH₁ IH₂ {
src    └────────────────────────────────────────
typ    └────────────────────────────────────────
doc    └────────────────────────────────────────
txt    └────────────────────────────────────────
par    └────────────────────────────────────────
pid        └──────────────┘└────────────────┘└──
st   ─────────────────────────────────────────┘
985      simp only [tr_normal, step_aux_read enc dec enc0 encdec, step_aux],
id                  └───────┘  └───────────┘ └─┘ └─┘ └──┘ └────┘  └──────┘
src  ───┘└─────────┘└───────┘└┘└───────────┘                └┘└──────┘└─
typ  ───┘└─────────┘└───────┘└┘└───────────┘└─┘└─┘└──┘└────┘└┘└──────┘└─
doc  ───┘└─────────┘         └┘                             └┘└──────┘└─
txt  ───┘└─────────┘         └┘                             └┘        └─
par  ───┘└─────────┘         └┘                             └┘        └─
pid  ──────────────┘         └┘                             └┘        └──
st   ─────────────────────────────────────────────────────────────────────┘└─
986      change (tape.mk' L R).1 with R.head,
id               └──────┘           └────┘
src  ───┘└─────┘ └──────┘  └───────┘└────┘└─
typ  ───┘└─────┘ └──────┘└───────┘└────┘└─
doc  ───┘└─────┘           └───────┘      └─
txt  ───┘└─────┘           └───────┘      └─
par  ───┘└─────┘           └───────┘      └─
pid  ──────────┘           └───────┘      └─
st   ──────────────────────────────────────┘└─
987      cases p R.head v; [apply IH₂, apply IH₁] },
id              └────┘ 
src  ───┘└────┘ └────┘ └─┘└────┘   └┘└────┘   └─┘
typ  ───┘└────┘└────┘└─┘└────┘   └┘└────┘   └─┘
doc  ───┘└────┘        └─┘└────┘   └┘└────┘   └─┘
txt  ───┘└────┘        └─┘└────┘   └┘└────┘   └─┘
par  ───┘└────┘        └─┘└────┘   └┘└────┘   └─┘
pid  ─────────┘        └───────┘   └──────┘   └─┘
st   ───────────────────────────────────────────┘└─┘
988    case TM1.stmt.goto : l {
src    └────────────────────────
typ    └────────────────────────
doc    └────────────────────────
txt    └────────────────────────
par    └────────────────────────
pid        └────────────┘└──┘└──
st   ─────────────────────────┘
989      simp only [tr_normal, step_aux_read enc dec enc0 encdec, step_aux],
id                  └───────┘  └───────────┘ └─┘ └─┘ └──┘ └────┘  └──────┘
src  ───┘└─────────┘└───────┘└┘└───────────┘                └┘└──────┘└─
typ  ───┘└─────────┘└───────┘└┘└───────────┘└─┘└─┘└──┘└────┘└┘└──────┘└─
doc  ───┘└─────────┘         └┘                             └┘└──────┘└─
txt  ───┘└─────────┘         └┘                             └┘        └─
par  ───┘└─────────┘         └┘                             └┘        └─
pid  ──────────────┘         └┘                             └┘        └──
st   ─────────────────────────────────────────────────────────────────────┘└─
990      apply refl_trans_gen.refl },
id             └─────────────────┘
src  ───┘└────┘└─────────────────┘
typ  ───┘└────┘└─────────────────┘
doc  ───┘└────┘                   
txt  ───┘└────┘                   
par  ───┘└────┘                   
pid  ─────────┘                   └┘
st   ─────────────────────────────┘└┘
991    case TM1.stmt.halt {
src    └────────────────────
typ    └────────────────────
doc    └────────────────────
txt    └────────────────────
par    └────────────────────
pid        └────────────┘└─
st   ───────────────────────
992      simp only [tr_normal, step_aux, tr_cfg, step_aux_move enc enc0,
id                  └───────┘  └──────┘  └────┘  └───────────┘ └─┘ └──┘
src  ───┘└─────────┘└───────┘└┘└──────┘└┘└────┘└┘└───────────┘       └─
typ  ───┘└─────────┘└───────┘└┘└──────┘└┘└────┘└┘└───────────┘└─┘└──┘└─
doc  ───┘└─────────┘         └┘└──────┘└┘      └┘                    └─
txt  ───┘└─────────┘         └┘        └┘      └┘                    └─
par  ───┘└─────────┘         └┘        └┘      └┘                    └─
pid  ──────────────┘         └┘        └┘      └┘                    └─
st   ────────────────────────────────────────────────────────────────────
993        tr_tape'_move_left enc enc0, tr_tape'_move_right enc enc0],
id         └────────────────┘ └─┘ └──┘  └─────────────────┘ └─┘ └──┘
src  ─────┘└────────────────┘       └┘└─────────────────┘       └─
typ  ─────┘└────────────────┘└─┘└──┘└┘└─────────────────┘└─┘└──┘└─
doc  ─────┘                         └┘                          └─
txt  ─────┘                         └┘                          └─
par  ─────┘                         └┘                          └─
pid  ─────┘                         └┘                          └──
st   ───────────────────────────────────────────────────────────────┘└─
994      apply refl_trans_gen.refl }
id             └─────────────────┘
src  ───┘└────┘└─────────────────┘└┘
typ  ───┘└────┘└─────────────────┘└┘
doc  ───┘└────┘                   └┘
txt  ───┘└────┘                   └┘
par  ───┘└────┘                   └┘
pid  ─────────┘                   └┘
st   ─────────────────────────────┘
995  end
st   └─┘
996  
997  omit enc0 encdec
998  open_locale classical
999  parameters [fintype Γ]
id               └─────┘
src              └─────┘
typ              └─────┘
doc              └─────┘
1000  noncomputable def writes : stmt₁ → finset Λ'
id                              └───┘  └────┘ └┘
src                             └───┘   └────┘ └┘
typ                             └───┘  └────┘ └┘
doc                             └───┘   └────┘
1001  | (stmt.move d q)       := writes q
id      └───────┘              └────┘
src     └───────┘
typ     └───────┘              └────┘
1002  | (stmt.write f q)      := finset.univ.image (λ a, Λ'.write a q) ∪ writes q
id      └────────┘             └─────────┘└────┘      └──────┘      └────┘
src     └────────┘              └─────────┘└────┘       └──────┘      
typ     └────────┘             └─────────┘└────┘      └──────┘      └────┘
doc                             └─────────┘└────┘
1003  | (stmt.load f q)       := writes q
id      └───────┘              └────┘
src     └───────┘
typ     └───────┘              └────┘
1004  | (stmt.branch p q₁ q₂) := writes q₁ ∪ writes q₂
id      └─────────┘   └┘ └┘     └────┘     └────┘
src     └─────────┘                       
typ     └─────────┘   └┘ └┘     └────┘     └────┘
1005  | (stmt.goto l)         := ∅
id      └───────┘               
src     └───────┘               
typ     └───────┘               
1006  | stmt.halt             := ∅
id     └───────┘                
src    └───────┘                
typ    └───────┘                
1007  
1008  noncomputable def tr_supp (S : finset Λ) : finset Λ' :=
id                                  └────┘     └────┘ └┘
src                                 └────┘      └────┘ └┘
typ                                 └────┘     └────┘ └┘
doc                                 └────┘      └────┘
1009  S.bind (λ l, insert (Λ'.normal l) (writes (M l)))
id   └───┘      └────┘  └───────┘    └────┘   
src   └───┘       └────┘  └───────┘     └────┘
typ  └───┘      └────┘  └───────┘    └────┘   
doc   └───┘
1010  
1011  theorem supports_stmt_move {S d q} :
1012    supports_stmt S (move d q) = supports_stmt S q :=
id     └───────────┘   └──┘     └───────────┘  
src    └───────────┘    └──┘       └───────────┘
typ    └───────────┘   └──┘     └───────────┘  
1013  suffices ∀ {i}, supports_stmt S (stmt.move d^[i] q) = _, from this,
id                  └───────────┘   └───────┘ └┘            └──┘
src                  └───────────┘    └───────┘  └┘     
typ                 └───────────┘   └───────┘ └┘            └──┘
1014  by intro; induction i generalizing q; simp only [*, nat.iterate]; refl
id                                                      └─────────┘
src     └───┘  └────────┘ └─────────────┘  └────────────┘└─────────┘  └────
typ     └───┘  └────────┘└─────────────┘  └────────────┘└─────────┘  └────
doc     └───┘  └────────┘ └─────────────┘  └────────────┘             └────
txt     └───┘  └────────┘ └─────────────┘  └────────────┘             └────
par     └───┘  └────────┘ └─────────────┘  └────────────┘             └────
pid                      └────────────┘      └──┘└───┘                 
st     └────────────────────────────────────────────────────────────────────
1015  
src  
typ  
doc  
txt  
par  
pid  
st   
1016  theorem supports_stmt_write {S l q} :
1017    supports_stmt S (write l q) = supports_stmt S q :=
id     └───────────┘   └───┘     └───────────┘  
src    └───────────┘    └───┘       └───────────┘
typ    └───────────┘   └───┘     └───────────┘  
1018  by induction l with a l IH; simp only [write, supports_stmt, *]
id                                         └───┘  └───────────┘
src     └────────┘ └──────────┘  └─────────┘└───┘└┘└───────────┘└────
typ     └────────┘└──────────┘  └─────────┘└───┘└┘└───────────┘└────
doc     └────────┘ └──────────┘  └─────────┘     └┘             └────
txt     └────────┘ └──────────┘  └─────────┘     └┘             └────
par     └────────┘ └──────────┘  └─────────┘     └┘             └────
pid               └─────────┘      └──┘└┘     └┘             └──┘
st     └─────────────────────────────────────────────────────────────
1019  
src  
typ  
doc  
txt  
par  
pid  
st   
1020  local attribute [simp] supports_stmt_move supports_stmt_write
id                          └────────────────┘ └─────────────────┘
src                         └────────────────┘ └─────────────────┘
typ                         └────────────────┘ └─────────────────┘
doc                   └──┘
1021  
1022  theorem supports_stmt_read {S} : ∀ {f : Γ → stmt'},
id                                             └───┘
src                                              └───┘
typ                                            └───┘
doc                                              └───┘
1023    (∀ a, supports_stmt S (f a)) → supports_stmt S (read f) :=
id          └───────────┘         └───────────┘   └──┘ 
src          └───────────┘            └───────────┘    └──┘
typ         └───────────┘         └───────────┘   └──┘ 
1024  suffices ∀ i (f : vector bool i → stmt'),
id                    └────┘ └──┘   └───┘
src                    └────┘ └──┘     └───┘
typ                   └────┘ └──┘   └───┘
doc                                    └───┘
1025    (∀ v, supports_stmt S (f v)) → supports_stmt S (read_aux i f),
id          └───────────┘         └───────────┘   └──────┘  
src          └───────────┘            └───────────┘    └──────┘
typ         └───────────┘         └───────────┘   └──────┘  
1026  from λ f hf, this n _ (by intro; simp only [supports_stmt_move, hf]),
id           └┘  └──┘                          └────────────────┘  └┘
src                            └───┘  └─────────┘└────────────────┘└┘  
typ          └┘  └──┘        └───┘  └─────────┘└────────────────┘└┘└┘
doc                            └───┘  └─────────┘                  └┘  
txt                            └───┘  └─────────┘                  └┘  
par                            └───┘  └─────────┘                  └┘  
pid                                       └──┘└┘                  └┘  
st                            └────────────────────────────────────────┘
1027  λ i f hf, begin
id       └┘
typ      └┘
st             └─────
1028    induction i with i IH, {exact hf _},
id                                  └┘
src    └────────┘ └────────┘   └────┘  └┘
typ    └────────┘└────────┘   └────┘└┘└┘
doc    └────────┘ └────────┘   └────┘  └┘
txt    └────────┘ └────────┘   └────┘  └┘
par    └────────┘ └────────┘   └────┘  └┘
pid              └───────┘          └┘
st   ──────────────────────┘└───────────┘└┘
1029    split; apply IH; intro; apply hf,
src    └───┘  └────┘    └───┘  └────┘
typ    └───┘  └────┘    └───┘  └────┘
doc    └───┘  └────┘    └───┘  └────┘
txt    └───┘  └────┘    └───┘  └────┘
par    └───┘  └────┘    └───┘  └────┘
pid                                
st   ─────────────────────────────────┘└─
1030  end
st   ──┘
1031  
1032  theorem tr_supports {S} (ss : supports M S) :
id                                 └──────┘  
src                                └──────┘
typ                                └──────┘  
doc                                └──────┘
1033    supports tr (tr_supp S) :=
id     └──────┘ └┘  └─────┘ 
src    └──────┘ └┘  └─────┘
typ    └──────┘ └┘  └─────┘ 
doc    └──────┘
1034  ⟨finset.mem_bind.2 ⟨_, ss.1, finset.mem_insert_self _ _⟩,
id    └─────────────┘      └┘   └────────────────────┘
src   └─────────────┘           └────────────────────┘
typ   └─────────────┘      └┘   └────────────────────┘
1035  λ q h, begin
id      
typ     
st          └─────
1036    suffices : ∀ q, supports_stmt S q →
id                     └───────────┘
src    └─────────┘ └┘                 
typ    └─────────┘ └┘ └───────────┘   
doc    └─────────┘ └┘                 
txt    └─────────┘ └┘                 
par    └─────────┘ └┘                 
pid    └───────┘└┘ └┘                 
st   ──────────────────────────────────────
1037      (∀ q' ∈ writes q, q' ∈ tr_supp M S) →
src  ───┘  └────┘                    └┘ 
typ  ───┘  └────┘                    └┘ 
doc  ───┘  └────┘                    └┘ 
txt  ───┘  └────┘                    └┘ 
par  ───┘  └────┘                    └┘ 
pid  ───┘  └────┘                    └┘ 
st   ──────────────────────────────────────────
1038      supports_stmt (tr_supp M S) (tr_normal dec q) ∧
id                                    └───────┘        
src  ───┘                       └┘ └───────┘    └┘
typ  ───┘                       └┘ └───────┘    └┘
doc  ───┘                       └┘              └┘ 
txt  ───┘                       └┘              └┘ 
par  ───┘                       └┘              └┘ 
pid  ───┘                       └┘              └┘ 
st   ────────────────────────────────────────────────────
1039      ∀ q' ∈ writes q, supports_stmt (tr_supp M S) (tr enc dec M q'),
id              └────┘    └───────────┘  └─────┘      └┘ └─┘ └─┘ 
src  ───┘ └────┘└────┘  └───────────┘ └─────┘  └┘ └┘         
typ  ───┘ └────┘└────┘  └───────────┘ └─────┘ └┘ └┘└─┘└─┘  
doc  ───┘ └────┘                               └┘            
txt  ───┘ └────┘                               └┘            
par  ───┘ └────┘                               └┘            
pid  ───┘ └────┘                               └┘            
st   ─────────────────────────────────────────────────────────────────┘└─
1040    { rcases finset.mem_bind.1 h with ⟨l, hl, h⟩,
id              └─────────────┘   
src      └─────┘└─────────────┘└─┘ └──────────────┘
typ      └─────┘└─────────────┘└─┘└──────────────┘
doc      └─────┘               └─┘ └──────────────┘
txt      └─────┘               └─┘ └──────────────┘
par      └─────┘               └─┘ └──────────────┘
pid                           └─┘ └──────────────┘
st   ───┘└────────────────────────────────────────┘└─
1041      have := this _ (ss.2 _ hl) (λ q' hq,
id               └──┘    └┘
src      └──────┘    └─┘   └───┘  └┘  └───────
typ      └──────┘└──┘└─┘ └┘└───┘  └┘  └───────
doc      └──────┘    └─┘   └───┘  └┘  └───────
txt      └──────┘    └─┘   └───┘  └┘  └───────
par      └──────┘    └─┘   └───┘  └┘  └───────
pid      └───┘└─┘    └─┘   └───┘  └┘  └───────
st   ─────────────────────────────────────────
1042        finset.mem_bind.2 ⟨_, hl, finset.mem_insert_of_mem hq⟩),
id         └─────────────┘       └┘  └──────────────────────┘
src  ─────┘└─────────────┘└─┘ └─┘  └┘└──────────────────────┘  └┘
typ  ─────┘└─────────────┘└─┘ └─┘└┘└┘└──────────────────────┘  └┘
doc  ─────┘               └─┘ └─┘  └┘                          └┘
txt  ─────┘               └─┘ └─┘  └┘                          └┘
par  ─────┘               └─┘ └─┘  └┘                          └┘
pid  ─────┘               └─┘ └─┘  └┘                          └┘
st   ────────────────────────────────────────────────────────────┘└─
1043      rcases finset.mem_insert.1 h with rfl | h,
id              └───────────────┘   
src      └─────┘└───────────────┘└─┘ └───────────┘
typ      └─────┘└───────────────┘└─┘└───────────┘
doc      └─────┘                 └─┘ └───────────┘
txt      └─────┘                 └─┘ └───────────┘
par      └─────┘                 └─┘ └───────────┘
pid                             └─┘ └───────────┘
st   ────────────────────────────────────────────┘└─
1044      exacts [this.1, this.2 _ h] },
id               └──┘    └──┘     
src      └──────┘    └──┘    └───┘ └┘
typ      └──────┘└──┘└──┘└──┘└───┘└┘
doc      └──────┘    └──┘    └───┘ └┘
txt      └──────┘    └──┘    └───┘ └┘
par      └──────┘    └──┘    └───┘ └┘
pid            └┘    └──┘    └───┘ 
st   ───────────────────────────────┘└┘
1045    intros q hs hw, induction q,
id                               
src    └────────────┘  └────────┘
typ    └────────────┘  └────────┘
doc    └────────────┘  └────────┘
txt    └────────────┘  └────────┘
par    └────────────┘  └────────┘
pid          └──────┘           
st   ───────────────┘└───────────┘└─
1046    case TM1.stmt.move : d q IH {
src    └─────────────────────────────
typ    └─────────────────────────────
doc    └─────────────────────────────
txt    └─────────────────────────────
par    └─────────────────────────────
pid        └────────────┘└───────┘└──
st   ──────────────────────────────┘
1047      unfold writes at hw ⊢,
src  ───┘└───────────────────┘└─
typ  ───┘└───────────────────┘└─
doc  ───┘└───────────────────┘└─
txt  ───┘└───────────────────┘└─
par  ───┘└───────────────────┘└─
pid  ───────────────────────────
st   ────────────────────────┘└─
1048      replace IH := IH hs hw, refine ⟨_, IH.2⟩,
id                     └┘ └┘ └┘             └┘
src  ───┘└────────────┘      └┘└─────┘ └─┘  └─┘└─
typ  ───┘└────────────┘└┘└┘└┘└┘└─────┘ └─┘└┘└─┘└─
doc  ───┘└────────────┘      └┘└─────┘ └─┘  └─┘└─
txt  ───┘└────────────┘      └┘└─────┘ └─┘  └─┘└─
par  ───┘└────────────┘      └┘└─────┘ └─┘  └─┘└─
pid  ─────────────────┘      └───────┘ └─┘  └────
st   ─────────────────────────┘└────────────────┘└─
1049      cases d; simp only [tr_normal, nat.iterate, supports_stmt_move, IH] },
id                          └───────┘  └─────────┘  └────────────────┘  └┘
src  ───┘└────┘ └┘└─────────┘└───────┘└┘└─────────┘└┘└────────────────┘└┘  └┘
typ  ───┘└────┘└┘└─────────┘└───────┘└┘└─────────┘└┘└────────────────┘└┘└┘└┘
doc  ───┘└────┘ └┘└─────────┘         └┘           └┘                  └┘  └┘
txt  ───┘└────┘ └┘└─────────┘         └┘           └┘                  └┘  └┘
par  ───┘└────┘ └┘└─────────┘         └┘           └┘                  └┘  └┘
pid  ─────────┘ └───────────┘         └┘           └┘                  └┘  └─┘
st   ───────────────────────────────────────────────────────────────────────┘└┘
1050    case TM1.stmt.write : f q IH {
src    └──────────────────────────────
typ    └──────────────────────────────
doc    └──────────────────────────────
txt    └──────────────────────────────
par    └──────────────────────────────
pid        └─────────────┘└───────┘└──
st   ───────────────────────────────┘
1051      unfold writes at hw ⊢,
src  ───┘└───────────────────┘└─
typ  ───┘└───────────────────┘└─
doc  ───┘└───────────────────┘└─
txt  ───┘└───────────────────┘└─
par  ───┘└───────────────────┘└─
pid  ───────────────────────────
st   ────────────────────────┘└─
1052      simp only [finset.mem_image, finset.mem_union, finset.mem_univ,
id                  └──────────────┘  └──────────────┘  └─────────────┘
src  ───┘└─────────┘└──────────────┘└┘└──────────────┘└┘└─────────────┘└─
typ  ───┘└─────────┘└──────────────┘└┘└──────────────┘└┘└─────────────┘└─
doc  ───┘└─────────┘                └┘                └┘               └─
txt  ───┘└─────────┘                └┘                └┘               └─
par  ───┘└─────────┘                └┘                └┘               └─
pid  ──────────────┘                └┘                └┘               └─
st   ────────────────────────────────────────────────────────────────────
1053        exists_prop, true_and] at hw ⊢,
id         └─────────┘  └──────┘
src  ─────┘└─────────┘└┘└──────┘└───────┘└─
typ  ─────┘└─────────┘└┘└──────┘└───────┘└─
doc  ─────┘           └┘        └───────┘└─
txt  ─────┘           └┘        └───────┘└─
par  ─────┘           └┘        └───────┘└─
pid  ─────┘           └┘        └──────────
st   ───────────────────────────────────┘└─
1054      replace IH := IH hs (λ q hq, hw q (or.inr hq)),
id                     └┘ └┘          └┘    └────┘
src  ───┘└────────────┘      └─────┘    └────┘  └┘└─
typ  ───┘└────────────┘└┘└┘  └─────┘└┘  └────┘  └┘└─
doc  ───┘└────────────┘      └─────┘            └┘└─
txt  ───┘└────────────┘      └─────┘            └┘└─
par  ───┘└────────────┘      └─────┘            └┘└─
pid  ─────────────────┘      └─────┘            └───
st   ─────────────────────────────────────────────────┘└─
1055      refine ⟨supports_stmt_read _ $ λ a _ s,
id               └────────────────┘
src  ───┘└─────┘ └────────────────┘└─┘  └───────
typ  ───┘└─────┘ └────────────────┘└─┘  └───────
doc  ───┘└─────┘                   └─┘  └───────
txt  ───┘└─────┘                   └─┘  └───────
par  ───┘└─────┘                   └─┘  └───────
pid  ──────────┘                   └─┘  └───────
st   ────────────────────────────────────────────
1056        hw _ (or.inl ⟨_, rfl⟩), λ q' hq, _⟩,
id         └┘    └────┘     └─┘
src  ─────┘  └─┘ └────┘ └─┘└─┘└──┘ └────────┘└─
typ  ─────┘└┘└─┘ └────┘ └─┘└─┘└──┘ └────────┘└─
doc  ─────┘  └─┘        └─┘   └──┘ └────────┘└─
txt  ─────┘  └─┘        └─┘   └──┘ └────────┘└─
par  ─────┘  └─┘        └─┘   └──┘ └────────┘└─
pid  ─────┘  └─┘        └─┘   └──┘ └───────────
st   ────────────────────────────────────────┘└─
1057      rcases hq with ⟨a, q₂, rfl⟩ | hq,
id              └┘
src  ───┘└─────┘  └─────────────────────┘└─
typ  ───┘└─────┘└┘└─────────────────────┘└─
doc  ───┘└─────┘  └─────────────────────┘└─
txt  ───┘└─────┘  └─────────────────────┘└─
par  ───┘└─────┘  └─────────────────────┘└─
pid  ──────────┘  └────────────────────────
st   ───────────────────────────────────┘└─
1058      { simp only [tr, supports_stmt_write, supports_stmt_move, IH.1] },
id                    └┘  └─────────────────┘  └────────────────┘  └┘
src  ─────┘└─────────┘└┘└┘└─────────────────┘└┘└────────────────┘└┘  └──┘└──
typ  ─────┘└─────────┘└┘└┘└─────────────────┘└┘└────────────────┘└┘└┘└──┘└──
doc  ─────┘└─────────┘  └┘                   └┘                  └┘  └──┘└──
txt  ─────┘└─────────┘  └┘                   └┘                  └┘  └──┘└──
par  ─────┘└─────────┘  └┘                   └┘                  └┘  └──┘└──
pid  ────────────────┘  └┘                   └┘                  └┘  └──────
st   ────┘└─────────────────────────────────────────────────────────────┘└─
1059      { exact IH.2 _ hq } },
id               └┘     └┘
src  ─────┘└────┘  └───┘  └─┘
typ  ─────┘└────┘└┘└───┘└┘└─┘
doc  ─────┘└────┘  └───┘  └─┘
txt  ─────┘└────┘  └───┘  └─┘
par  ─────┘└────┘  └───┘  └─┘
pid  ───────────┘  └───┘  └──┘
st   ─────────────────────┘└──┘
1060    case TM1.stmt.load : a q IH {
src    └─────────────────────────────
typ    └─────────────────────────────
doc    └─────────────────────────────
txt    └─────────────────────────────
par    └─────────────────────────────
pid        └────────────┘└───────┘└──
st   ──────────────────────────────┘
1061      unfold writes at hw ⊢,
src  ───┘└───────────────────┘└─
typ  ───┘└───────────────────┘└─
doc  ───┘└───────────────────┘└─
txt  ───┘└───────────────────┘└─
par  ───┘└───────────────────┘└─
pid  ───────────────────────────
st   ────────────────────────┘└─
1062      replace IH := IH hs hw,
id                     └┘ └┘ └┘
src  ───┘└────────────┘      └─
typ  ───┘└────────────┘└┘└┘└┘└─
doc  ───┘└────────────┘      └─
txt  ───┘└────────────┘      └─
par  ───┘└────────────┘      └─
pid  ─────────────────┘      └─
st   ─────────────────────────┘└─
1063      refine ⟨supports_stmt_read _ (λ a, IH.1), IH.2⟩ },
id               └────────────────┘                └┘
src  ───┘└─────┘ └────────────────┘└─┘  └──┘  └───┘  └──┘
typ  ───┘└─────┘ └────────────────┘└─┘  └──┘  └───┘└┘└──┘
doc  ───┘└─────┘                   └─┘  └──┘  └───┘  └──┘
txt  ───┘└─────┘                   └─┘  └──┘  └───┘  └──┘
par  ───┘└─────┘                   └─┘  └──┘  └───┘  └──┘
pid  ──────────┘                   └─┘  └──┘  └───┘  └───┘
st   ───────────────────────────────────────────────────┘└┘
1064    case TM1.stmt.branch : p q₁ q₂ IH₁ IH₂ {
src    └────────────────────────────────────────
typ    └────────────────────────────────────────
doc    └────────────────────────────────────────
txt    └────────────────────────────────────────
par    └────────────────────────────────────────
pid        └──────────────┘└────────────────┘└──
st   ─────────────────────────────────────────┘
1065      unfold writes at hw ⊢,
src  ───┘└───────────────────┘└─
typ  ───┘└───────────────────┘└─
doc  ───┘└───────────────────┘└─
txt  ───┘└───────────────────┘└─
par  ───┘└───────────────────┘└─
pid  ───────────────────────────
st   ────────────────────────┘└─
1066      simp only [finset.mem_union] at hw ⊢,
id                  └──────────────┘
src  ───┘└─────────┘└──────────────┘└───────┘└─
typ  ───┘└─────────┘└──────────────┘└───────┘└─
doc  ───┘└─────────┘                └───────┘└─
txt  ───┘└─────────┘                └───────┘└─
par  ───┘└─────────┘                └───────┘└─
pid  ──────────────┘                └──────────
st   ───────────────────────────────────────┘└─
1067      replace IH₁ := IH₁ hs.1 (λ q hq, hw q (or.inl hq)),
id                      └─┘ └┘            └┘    └────┘
src  ───┘└─────────────┘     └─┘  └─────┘    └────┘  └┘└─
typ  ───┘└─────────────┘└─┘└┘└─┘  └─────┘└┘  └────┘  └┘└─
doc  ───┘└─────────────┘     └─┘  └─────┘            └┘└─
txt  ───┘└─────────────┘     └─┘  └─────┘            └┘└─
par  ───┘└─────────────┘     └─┘  └─────┘            └┘└─
pid  ──────────────────┘     └─┘  └─────┘            └───
st   ─────────────────────────────────────────────────────┘└─
1068      replace IH₂ := IH₂ hs.2 (λ q hq, hw q (or.inr hq)),
id                      └─┘ └┘            └┘    └────┘
src  ───┘└─────────────┘     └─┘  └─────┘    └────┘  └┘└─
typ  ───┘└─────────────┘└─┘└┘└─┘  └─────┘└┘  └────┘  └┘└─
doc  ───┘└─────────────┘     └─┘  └─────┘            └┘└─
txt  ───┘└─────────────┘     └─┘  └─────┘            └┘└─
par  ───┘└─────────────┘     └─┘  └─────┘            └┘└─
pid  ──────────────────┘     └─┘  └─────┘            └───
st   ─────────────────────────────────────────────────────┘└─
1069      exact ⟨supports_stmt_read _ (λ a, ⟨IH₁.1, IH₂.1⟩),
id              └────────────────┘
src  ───┘└────┘ └────────────────┘└─┘  └──┘    └──┘   └─────
typ  ───┘└────┘ └────────────────┘└─┘  └──┘    └──┘   └─────
doc  ───┘└────┘                   └─┘  └──┘    └──┘   └─────
txt  ───┘└────┘                   └─┘  └──┘    └──┘   └─────
par  ───┘└────┘                   └─┘  └──┘    └──┘   └─────
pid  ─────────┘                   └─┘  └──┘    └──┘   └─────
st   ───────────────────────────────────────────────────────
1070        λ q, or.rec (IH₁.2 _) (IH₂.2 _)⟩ },
id              └────┘  └─┘       └─┘
src  ─────┘ └──┘└────┘    └────┘    └─────┘
typ  ─────┘ └──┘└────┘ └─┘└────┘ └─┘└─────┘
doc  ─────┘ └──┘          └────┘    └─────┘
txt  ─────┘ └──┘          └────┘    └─────┘
par  ─────┘ └──┘          └────┘    └─────┘
pid  ─────┘ └──┘          └────┘    └──────┘
st   ──────────────────────────────────────┘└┘
1071    case TM1.stmt.goto : l {
src    └────────────────────────
typ    └────────────────────────
doc    └────────────────────────
txt    └────────────────────────
par    └────────────────────────
pid        └────────────┘└──┘└──
st   ─────────────────────────┘
1072      refine ⟨_, λ _, false.elim⟩,
id                       └────────┘
src  ───┘└─────┘ └─┘ └──┘└────────┘└─
typ  ───┘└─────┘ └─┘ └──┘└────────┘└─
doc  ───┘└─────┘ └─┘ └──┘          └─
txt  ───┘└─────┘ └─┘ └──┘          └─
par  ───┘└─────┘ └─┘ └──┘          └─
pid  ──────────┘ └─┘ └──┘          └──
st   ──────────────────────────────┘└─
1073      refine supports_stmt_read _ (λ a _ s, _),
id              └────────────────┘
src  ───┘└─────┘└────────────────┘└─┘  └────────┘└─
typ  ───┘└─────┘└────────────────┘└─┘  └────────┘└─
doc  ───┘└─────┘                  └─┘  └────────┘└─
txt  ───┘└─────┘                  └─┘  └────────┘└─
par  ───┘└─────┘                  └─┘  └────────┘└─
pid  ──────────┘                  └─┘  └───────────
st   ───────────────────────────────────────────┘└─
1074      exact finset.mem_bind.2 ⟨_, hs _ _, finset.mem_insert_self _ _⟩ },
id             └─────────────┘       └┘      └────────────────────┘
src  ───┘└────┘└─────────────┘└─┘ └─┘  └────┘└────────────────────┘└────┘
typ  ───┘└────┘└─────────────┘└─┘ └─┘└┘└────┘└────────────────────┘└────┘
doc  ───┘└────┘               └─┘ └─┘  └────┘                      └────┘
txt  ───┘└────┘               └─┘ └─┘  └────┘                      └────┘
par  ───┘└────┘               └─┘ └─┘  └────┘                      └────┘
pid  ─────────┘               └─┘ └─┘  └────┘                      └─────┘
st   ───────────────────────────────────────────────────────────────────┘└┘
1075    case TM1.stmt.halt {
src    └────────────────────
typ    └────────────────────
doc    └────────────────────
txt    └────────────────────
par    └────────────────────
pid        └────────────┘└─
st   ───────────────────────
1076      refine ⟨_, λ _, false.elim⟩,
id                       └────────┘
src  ───┘└─────┘ └─┘ └──┘└────────┘└─
typ  ───┘└─────┘ └─┘ └──┘└────────┘└─
doc  ───┘└─────┘ └─┘ └──┘          └─
txt  ───┘└─────┘ └─┘ └──┘          └─
par  ───┘└─────┘ └─┘ └──┘          └─
pid  ──────────┘ └─┘ └──┘          └──
st   ──────────────────────────────┘└─
1077      simp only [supports_stmt, supports_stmt_move, tr_normal] }
id                  └───────────┘  └────────────────┘  └───────┘
src  ───┘└─────────┘└───────────┘└┘└────────────────┘└┘└───────┘└┘└┘
typ  ───┘└─────────┘└───────────┘└┘└────────────────┘└┘└───────┘└┘└┘
doc  ───┘└─────────┘             └┘                  └┘         └┘└┘
txt  ───┘└─────────┘             └┘                  └┘         └┘└┘
par  ───┘└─────────┘             └┘                  └┘         └┘└┘
pid  ──────────────┘             └┘                  └┘         └─┘
st   ────────────────────────────────────────────────────────────┘
1078  end⟩
st   └─┘
1079  
1080  end
1081  
1082  end TM1to1
1083  
1084  namespace TM0to1
1085  
1086  section
1087  parameters {Γ : Type*} [inhabited Γ]
id                         └───────┘
src                          └───────┘
typ                        └───────┘
1088  parameters {Λ : Type*} [inhabited Λ]
id                         └───────┘
src                          └───────┘
typ                        └───────┘
1089  
1090  inductive Λ'
1091  | normal : Λ → Λ'
1092  | act : TM0.stmt Γ → Λ → Λ'
id           └──────┘
src          └──────┘
typ          └──────┘
doc          └──────┘
1093  instance : inhabited Λ' := ⟨Λ'.normal (default _)⟩
id              └───────┘ └┘     └───────┘  └─────┘
src             └───────┘ └┘     └───────┘  └─────┘
typ             └───────┘ └┘     └───────┘  └─────┘
1094  
1095  local notation `cfg₀` := TM0.cfg Γ Λ
id                            └─────┘
src                           └─────┘
typ                           └─────┘
doc                           └─────┘
1096  local notation `stmt₁` := TM1.stmt Γ Λ' unit
id                             └──────┘      └──┘
src                            └──────┘      └──┘
typ                            └──────┘      └──┘
doc                            └──────┘      └──┘
1097  local notation `cfg₁` := TM1.cfg Γ Λ' unit
id                            └─────┘      └──┘
src                           └─────┘      └──┘
typ                           └─────┘      └──┘
doc                           └─────┘      └──┘
1098  
1099  parameters (M : TM0.machine Γ Λ)
id                   └─────────┘
src                  └─────────┘
typ                  └─────────┘
doc                  └─────────┘
1100  
1101  open TM1.stmt
1102  
1103  def tr : Λ' → stmt₁
id            └┘  └───┘
src           └┘   └───┘
typ           └┘  └───┘
doc                └───┘
1104  | (Λ'.normal q) :=
id      └───────┘ 
src     └───────┘
typ     └───────┘ 
1105    branch (λ a _, (M q a).is_none) halt $
id     └────┘            └─────┘   └──┘
src    └────┘                └─────┘   └──┘
typ    └────┘            └─────┘   └──┘
1106    goto (λ a _, match M q a with
id     └──┘                
src    └──┘
typ    └──┘                
1107    | none := default _
id       └──┘    └─────┘
src      └──┘    └─────┘
typ      └──┘    └─────┘
1108    | some (q', s) := Λ'.act s q'
id       └──┘ └┘       └────┘
src      └──┘           └────┘
typ      └──┘ └┘       └────┘
1109    end)
1110  | (Λ'.act (TM0.stmt.move d) q) :=
id      └────┘  └───────────┘   
src     └────┘  └───────────┘
typ     └────┘  └───────────┘   
1111    move d $ goto (λ _ _, Λ'.normal q)
id     └──┘     └──┘       └───────┘
src    └──┘     └──┘         └───────┘
typ    └──┘     └──┘       └───────┘
1112  | (Λ'.act (TM0.stmt.write a) q) :=
id      └────┘  └────────────┘   
src     └────┘  └────────────┘
typ     └────┘  └────────────┘   
1113    write (λ _ _, a) $ goto (λ _ _, Λ'.normal q)
id     └───┘            └──┘       └───────┘
src    └───┘              └──┘         └───────┘
typ    └───┘            └──┘       └───────┘
1114  
1115  def tr_cfg : cfg₀ → cfg₁
id                └──┘  └──┘
src               └──┘   └──┘
typ               └──┘  └──┘
doc               └──┘   └──┘
1116  | ⟨q, T⟩ := ⟨cond (M q T.1).is_some
id              └──┘        └─────┘
src               └──┘         └─────┘
typ             └──┘        └─────┘
1117    (some (Λ'.normal q)) none, (), T⟩
id      └──┘  └───────┘     └──┘  └┘
src     └──┘  └───────┘     └──┘  └┘
typ     └──┘  └───────┘     └──┘  └┘
1118  
1119  theorem tr_respects : respects (TM0.step M) (TM1.step tr)
id                         └──────┘  └──────┘    └──────┘ └┘
src                        └──────┘  └──────┘     └──────┘ └┘
typ                        └──────┘  └──────┘    └──────┘ └┘
doc                                  └──────┘
1120    (λ a b, tr_cfg a = b) :=
id           └────┘   
src            └────┘   
typ          └────┘   
1121  fun_respects.2 $ λ ⟨q, T⟩, begin
id   └──────────┘      
src  └──────────┘
typ  └──────────┘      
st                              └─────
1122    cases e : M q T.1,
id                 
src    └────┘ └─┘   └┘
typ    └────┘ └─┘└┘
doc    └────┘ └─┘   └┘
txt    └────┘ └─┘   └┘
par    └────┘ └─┘   └┘
pid          └─┘   └┘
st   ──────────────────┘└─
1123    { simp only [TM0.step, tr_cfg, e]; exact eq.refl none },
id                  └──────┘  └────┘           └─────┘ └──┘
src      └─────────┘└──────┘└┘└────┘└┘   └────┘└─────┘└──┘
typ      └─────────┘└──────┘└┘└────┘└┘  └────┘└─────┘└──┘
doc      └─────────┘└──────┘└┘      └┘   └────┘           
txt      └─────────┘        └┘      └┘   └────┘           
par      └─────────┘        └┘      └┘   └────┘           
pid          └──┘└┘        └┘      └┘                   
st   ───┘└──────────────────────────────────────────────────┘└┘
1124    cases val with q' s,
id           └─┘
src    └────┘   └────────┘
typ    └────┘└─┘└────────┘
doc    └────┘   └────────┘
txt    └────┘   └────────┘
par    └────┘   └────────┘
pid            └────────┘
st   ────────────────────┘└─
1125    simp only [frespects, TM0.step, tr_cfg, e, option.is_some, cond, option.map_some'],
id                └───────┘  └──────┘  └────┘    └────────────┘  └──┘  └──────────────┘
src    └─────────┘└───────┘└┘└──────┘└┘└────┘└┘ └┘└────────────┘└┘└──┘└┘└──────────────┘
typ    └─────────┘└───────┘└┘└──────┘└┘└────┘└┘└┘└────────────┘└┘└──┘└┘└──────────────┘
doc    └─────────┘         └┘└──────┘└┘      └┘ └┘              └┘    └┘                
txt    └─────────┘         └┘        └┘      └┘ └┘              └┘    └┘                
par    └─────────┘         └┘        └┘      └┘ └┘              └┘    └┘                
pid        └──┘└┘         └┘        └┘      └┘ └┘              └┘    └┘                
st   ───────────────────────────────────────────────────────────────────────────────────┘└─
1126    have : TM1.step (tr M) ⟨some (Λ'.act s q'), (), T⟩ =
id            └──────┘  └┘ 
src    └─────┘└──────┘ └┘ └┘               └─┘  └┘ └┘ 
typ    └─────┘└──────┘ └┘└┘               └─┘  └┘ └┘ 
doc    └─────┘            └┘               └─┘  └┘ └┘ 
txt    └─────┘            └┘               └─┘  └┘ └┘ 
par    └─────┘            └┘               └─┘  └┘ └┘ 
pid    └───┘└┘            └┘               └─┘  └┘ └┘ 
st   ───────────────────────────────────────────────────────
1127      some ⟨some (Λ'.normal q'), (), TM0.step._match_1 T s⟩,
id             └──┘            └┘   └┘  └───────────────┘  
src  ───┘     └──┘            └─┘└┘└┘└───────────────┘  
typ  ───┘     └──┘          └┘└─┘└┘└┘└───────────────┘
doc  ───┘                     └─┘  └┘                   
txt  ───┘                     └─┘  └┘                   
par  ───┘                     └─┘  └┘                   
pid  ───┘                     └─┘  └┘                   
st   ────────────────────────────────────────────────────────┘└─
1128    { cases s with d a; refl },
id             
src      └────┘ └───────┘  └───┘
typ      └────┘└───────┘  └───┘
doc      └────┘ └───────┘  └───┘
txt      └────┘ └───────┘  └───┘
par      └────┘ └───────┘  └───┘
pid            └───────┘      
st   ───┘└─────────────────────┘└┘
1129    refine trans_gen.head _ (trans_gen.head' this _),
id            └────────────┘    └─────────────┘ └──┘
src    └─────┘└────────────┘└─┘ └─────────────┘    └─┘
typ    └─────┘└────────────┘└─┘ └─────────────┘└──┘└─┘
doc    └─────┘              └─┘                    └─┘
txt    └─────┘              └─┘                    └─┘
par    └─────┘              └─┘                    └─┘
pid                        └─┘                    └─┘
st   ─────────────────────────────────────────────────┘└─
1130    { unfold TM1.step TM1.step_aux tr has_mem.mem,
src      └─────────────────────────────────────────┘
typ      └─────────────────────────────────────────┘
doc      └─────────────────────────────────────────┘
txt      └─────────────────────────────────────────┘
par      └─────────────────────────────────────────┘
pid            └───────────────────────────────────┘
st   ───┘└─────────────────────────────────────────┘└─
1131      rw e, refl },
id          
src      └─┘   └───┘
typ      └─┘  └───┘
doc      └─┘   └───┘
txt      └─┘   └───┘
par      └─┘   └───┘
pid               
st   ───────┘└─────┘└┘
1132    cases e' : M q' _,
id                 └┘
src    └────┘  └─┘   └┘
typ    └────┘  └─┘└┘└┘
doc    └────┘  └─┘   └┘
txt    └────┘  └─┘   └┘
par    └────┘  └─┘   └┘
pid           └─┘   └┘
st   ──────────────────┘└─
1133    { apply refl_trans_gen.single,
id             └───────────────────┘
src      └────┘└───────────────────┘
typ      └────┘└───────────────────┘
doc      └────┘
txt      └────┘
par      └────┘
pid           
st   ───┘└─────────────────────────┘└─
1134      unfold TM1.step TM1.step_aux tr has_mem.mem,
src      └─────────────────────────────────────────┘
typ      └─────────────────────────────────────────┘
doc      └─────────────────────────────────────────┘
txt      └─────────────────────────────────────────┘
par      └─────────────────────────────────────────┘
pid            └───────────────────────────────────┘
st   ──────────────────────────────────────────────┘└─
1135      rw e', refl },
id          └┘
src      └─┘    └───┘
typ      └─┘└┘  └───┘
doc      └─┘    └───┘
txt      └─┘    └───┘
par      └─┘    └───┘
pid                
st   ────────┘└─────┘└┘
1136    { refl }
src      └───┘
typ      └───┘
doc      └───┘
txt      └───┘
par      └───┘
pid          
st   ────────┘└─
1137  end
st   ──┘
1138  
1139  end
1140  
1141  end TM0to1
1142  
1143  namespace TM2
1144  
1145  section
1146  parameters {K : Type*} [decidable_eq K] -- Index type of stacks
id                  └───┘   └──────────┘
src                          └──────────┘
typ                 └───┘   └──────────┘
1147  parameters (Γ : K → Type*) -- Type of stack elements
id                     
typ                    
1148  parameters (Λ : Type*) -- Type of function labels
id                  └───┘
typ                 └───┘
1149  parameters (σ : Type*) -- Type of variable settings
id                   └───┘
typ                  └───┘
1150  
1151  /-- The TM2 model removes the tape entirely from the TM1 model,
1152    replacing it with an arbitrary (finite) collection of stacks.
1153    The operation `push` puts an element on one of the stacks,
1154    and `pop` removes an element from a stack (and modifying the
1155    internal state based on the result). `peek` modifies the
1156    internal state but does not remove an element. -/
1157  inductive stmt
1158  | push {} : ∀ k, (σ → Γ k) → stmt → stmt
id                         
typ                        
1159  | peek {} : ∀ k, (σ → option (Γ k) → σ) → stmt → stmt
id                       └────┘    
src                        └────┘
typ                      └────┘    
1160  | pop {} : ∀ k, (σ → option (Γ k) → σ) → stmt → stmt
id                      └────┘    
src                       └────┘
typ                     └────┘    
1161  | load : (σ → σ) → stmt → stmt
id               
typ              
1162  | branch : (σ → bool) → stmt → stmt → stmt
id                  └──┘
src                  └──┘
typ                 └──┘
1163  | goto {} : (σ → Λ) → stmt
id                  
typ                 
1164  | halt {} : stmt
1165  open stmt
1166  
1167  instance stmt.inhabited : inhabited stmt := ⟨halt⟩
id                             └───────┘ └──┘     └──┘
src                            └───────┘ └──┘     └──┘
typ                            └───────┘ └──┘     └──┘
doc                                      └──┘
1168  
1169  structure cfg :=
1170  (l : option Λ)
id        └────┘ 
src       └────┘
typ       └────┘ 
1171  (var : σ)
id          
typ         
1172  (stk : ∀ k, list (Γ k))
id              └──┘   
src              └──┘
typ             └──┘   
1173  
1174  instance cfg.inhabited [inhabited σ] [∀ k, inhabited (Γ k)] : inhabited cfg :=
id                           └───────┘        └───────┘        └───────┘ └─┘
src                          └───────┘          └───────┘          └───────┘ └─┘
typ                          └───────┘        └───────┘        └───────┘ └─┘
1175  ⟨by constructor; intros; apply default⟩
id                                  └─────┘
src      └─────────┘  └────┘  └────┘└─────┘
typ      └─────────┘  └────┘  └────┘└─────┘
doc      └─────────┘  └────┘  └────┘
txt      └─────────┘  └────┘  └────┘
par      └─────────┘  └────┘  └────┘
pid                                
st      └─────────────────────────────────┘
1176  
1177  parameters {Γ Λ σ K}
1178  def step_aux : stmt → σ → (∀ k, list (Γ k)) → cfg
id                  └──┘          └──┘        └─┘
src                 └──┘             └──┘          └─┘
typ                 └──┘          └──┘        └─┘
doc                 └──┘
1179  | (push k f q)     v S := step_aux q v (dwrite S k (f v :: S k))
id      └──┘              └──────┘      └────┘          └┘
src     └──┘                                 └────┘          └┘
typ     └──┘              └──────┘      └────┘          └┘
1180  | (peek k f q)     v S := step_aux q (f v (S k).head') S
id      └──┘              └──────┘             └───┘
src     └──┘                                        └───┘
typ     └──┘              └──────┘             └───┘
1181  | (pop k f q)      v S := step_aux q (f v (S k).head') (dwrite S k (S k).tail)
id      └─┘               └──────┘             └───┘    └────┘          └──┘
src     └─┘                                         └───┘    └────┘          └──┘
typ     └─┘               └──────┘             └───┘    └────┘          └──┘
1182  | (load a q)       v S := step_aux q (a v) S
id      └──┘               └──────┘
src     └──┘
typ     └──┘               └──────┘
1183  | (branch f q₁ q₂) v S :=
id      └────┘  └┘ └┘   
src     └────┘
typ     └────┘  └┘ └┘   
1184    cond (f v) (step_aux q₁ v S) (step_aux q₂ v S)
id     └──┘        └──────┘          └──────┘
src    └──┘
typ    └──┘        └──────┘          └──────┘
1185  | (goto f)         v S := ⟨some (f v), v, S⟩
id      └──┘                 └──┘
src     └──┘                    └──┘
typ     └──┘                 └──┘
1186  | halt             v S := ⟨none, v, S⟩
id     └──┘                   └──┘
src    └──┘                     └──┘
typ    └──┘                   └──┘
1187  
1188  def step (M : Λ → stmt) : cfg → option cfg
id                    └──┘    └─┘  └────┘ └─┘
src                    └──┘    └─┘   └────┘ └─┘
typ                   └──┘    └─┘  └────┘ └─┘
doc                    └──┘
1189  | ⟨none,   v, S⟩ := none
id      └──┘             └──┘
src     └──┘             └──┘
typ     └──┘             └──┘
1190  | ⟨some l, v, S⟩ := some (step_aux (M l) v S)
id      └──┘          └──┘  └──────┘  
src     └──┘             └──┘  └──────┘
typ     └──┘          └──┘  └──────┘  
1191  
1192  def reaches (M : Λ → stmt) : cfg → cfg → Prop :=
id                       └──┘    └─┘   └─┘
src                       └──┘    └─┘   └─┘
typ                      └──┘    └─┘   └─┘
doc                       └──┘
1193  refl_trans_gen (λ a b, b ∈ step M a)
id   └────────────┘         └──┘  
src  └────────────┘            └──┘
typ  └────────────┘         └──┘  
doc  └────────────┘
1194  
1195  variables [inhabited Λ] [inhabited σ]
id              └───────┘     └───────┘
src             └───────┘     └───────┘
typ             └───────┘     └───────┘
1196  def init (k) (L : list (Γ k)) : cfg :=
id                     └──┘        └─┘
src                    └──┘          └─┘
typ                    └──┘        └─┘
1197  ⟨some (default _), default _, dwrite (λ _, []) k L⟩
id    └──┘  └─────┘     └─────┘    └────┘      └┘   
src   └──┘  └─────┘     └─────┘    └────┘       └┘
typ   └──┘  └─────┘     └─────┘    └────┘      └┘   
1198  
1199  def eval (M : Λ → stmt) (k) (L : list (Γ k)) : roption (list (Γ k)) :=
id                    └──┘           └──┘        └─────┘  └──┘   
src                    └──┘           └──┘          └─────┘  └──┘
typ                   └──┘           └──┘        └─────┘  └──┘   
doc                    └──┘                         └─────┘
1200  (eval (step M) (init k L)).map $ λ c, c.stk k
id    └──┘  └──┘    └──┘    └─┘        └──┘ 
src   └──┘  └──┘     └──┘      └─┘          └──┘
typ   └──┘  └──┘    └──┘    └─┘        └──┘ 
doc                            └─┘
1201  
1202  variables [fintype K] [∀ k, fintype (Γ k)] [fintype σ]
id              └─────┘         └─────┘        └─────┘
src             └─────┘          └─────┘         └─────┘
typ             └─────┘         └─────┘        └─────┘
doc             └─────┘          └─────┘         └─────┘
1203  def supports_stmt (S : finset Λ) : stmt → Prop
id                          └────┘     └──┘ 
src                         └────┘      └──┘
typ                         └────┘     └──┘ 
doc                         └────┘      └──┘
1204  | (push k f q)     := supports_stmt q
id      └──┘              └───────────┘
src     └──┘
typ     └──┘              └───────────┘
1205  | (peek k f q)     := supports_stmt q
id      └──┘              └───────────┘
src     └──┘
typ     └──┘              └───────────┘
1206  | (pop k f q)      := supports_stmt q
id      └─┘               └───────────┘
src     └─┘
typ     └─┘               └───────────┘
1207  | (load a q)       := supports_stmt q
id      └──┘              └───────────┘
src     └──┘
typ     └──┘              └───────────┘
1208  | (branch f q₁ q₂) := supports_stmt q₁ ∧ supports_stmt q₂
id      └────┘   └┘ └┘     └───────────┘     └───────────┘
src     └────┘                              
typ     └────┘   └┘ └┘     └───────────┘     └───────────┘
1209  | (goto l)         := ∀ v, l v ∈ S
id      └──┘                      
src     └──┘                        
typ     └──┘                      
1210  | halt             := true
id     └──┘                └──┘
src    └──┘                └──┘
typ    └──┘                └──┘
1211  
1212  def supports (M : Λ → stmt) (S : finset Λ) :=
id                        └──┘       └────┘ 
src                        └──┘       └────┘
typ                       └──┘       └────┘ 
doc                        └──┘       └────┘
1213  default Λ ∈ S ∧ ∀ q ∈ S, supports_stmt S (M q)
id   └─────┘            └───────────┘    
src  └─────┘                └───────────┘
typ  └─────┘            └───────────┘    
1214  
1215  open_locale classical
1216  noncomputable def stmts₁ : stmt → finset stmt
id                              └──┘  └────┘ └──┘
src                             └──┘   └────┘ └──┘
typ                             └──┘  └────┘ └──┘
doc                             └──┘   └────┘ └──┘
1217  | Q@(push k f q)     := insert Q (stmts₁ q)
id        └──┘              └────┘    └────┘
src       └──┘               └────┘
typ       └──┘              └────┘    └────┘
1218  | Q@(peek k f q)     := insert Q (stmts₁ q)
id        └──┘              └────┘    └────┘
src       └──┘               └────┘
typ       └──┘              └────┘    └────┘
1219  | Q@(pop k f q)      := insert Q (stmts₁ q)
id        └─┘               └────┘    └────┘
src       └─┘                └────┘
typ       └─┘               └────┘    └────┘
1220  | Q@(load a q)       := insert Q (stmts₁ q)
id        └──┘              └────┘    └────┘
src       └──┘               └────┘
typ       └──┘              └────┘    └────┘
1221  | Q@(branch f q₁ q₂) := insert Q (stmts₁ q₁ ∪ stmts₁ q₂)
id        └────┘   └┘ └┘     └────┘    └────┘     └────┘
src       └────┘             └────┘              
typ       └────┘   └┘ └┘     └────┘    └────┘     └────┘
1222  | Q@(goto l)         := {Q}
id        └──┘               
src       └──┘               
typ       └──┘               
1223  | Q@halt             := {Q}
id       └──┘                
src      └──┘                
typ      └──┘                
1224  
1225  theorem stmts₁_self {q} : q ∈ stmts₁ q :=
id                               └────┘ 
src                               └────┘
typ                              └────┘ 
1226  by cases q; apply finset.mem_insert_self
id                    └────────────────────┘
src     └────┘   └────┘└────────────────────┘
typ     └────┘  └────┘└────────────────────┘
doc     └────┘   └────┘                      
txt     └────┘   └────┘                      
par     └────┘   └────┘                      
pid                                        
st     └──────────────────────────────────────
1227  
src  
typ  
doc  
txt  
par  
pid  
st   
1228  theorem stmts₁_trans {q₁ q₂} :
1229    q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ :=
id     └┘  └────┘ └┘   └────┘ └┘  └────┘ └┘
src        └────┘      └────┘     └────┘
typ    └┘  └────┘ └┘   └────┘ └┘  └────┘ └┘
1230  begin
st   └─────
1231    intros h₁₂ q₀ h₀₁,
src    └───────────────┘
typ    └───────────────┘
doc    └───────────────┘
txt    └───────────────┘
par    └───────────────┘
pid          └─────────┘
st   ──────────────────┘└─
1232    induction q₂ with _ _ q IH _ _ q IH _ _ q IH _ q IH;
id               └┘
src    └────────┘  └─────────────────────────────────────┘
typ    └────────┘└┘└─────────────────────────────────────┘
doc    └────────┘  └─────────────────────────────────────┘
txt    └────────┘  └─────────────────────────────────────┘
par    └────────┘  └─────────────────────────────────────┘
pid               └────────────────────────────────────┘
st   ───────────────────────────────────────────────────────
1233      simp only [stmts₁] at h₁₂ ⊢;
id                  └────┘
src      └─────────┘└────┘└────────┘
typ      └─────────┘└────┘└────────┘
doc      └─────────┘      └────────┘
txt      └─────────┘      └────────┘
par      └─────────┘      └────────┘
pid          └──┘└┘      └──────┘
st   ─────────────────────────────────
1234      simp only [finset.mem_insert, finset.insert_empty_eq_singleton,
id                  └───────────────┘  └──────────────────────────────┘
src      └─────────┘└───────────────┘└┘└──────────────────────────────┘└─
typ      └─────────┘└───────────────┘└┘└──────────────────────────────┘└─
doc      └─────────┘                 └┘                                └─
txt      └─────────┘                 └┘                                └─
par      └─────────┘                 └┘                                └─
pid          └──┘└┘                 └┘                                └─
st   ────────────────────────────────────────────────────────────────────
1235        finset.mem_singleton, finset.mem_union] at h₁₂,
id         └──────────────────┘  └──────────────┘
src  ─────┘└──────────────────┘└┘└──────────────┘└──────┘
typ  ─────┘└──────────────────┘└┘└──────────────┘└──────┘
doc  ─────┘                    └┘                └──────┘
txt  ─────┘                    └┘                └──────┘
par  ─────┘                    └┘                └──────┘
pid  ─────┘                    └┘                └────┘
st   ───────────────────────────────────────────────────┘└─
1236    iterate 4 {
src    └───────────
typ    └───────────
doc    └───────────
txt    └───────────
par    └───────────
pid           └───
st   ──────────────
1237      rcases h₁₂ with rfl | h₁₂,
id              └─┘
src  ───┘└─────┘   └─────────────┘└─
typ  ───┘└─────┘└─┘└─────────────┘└─
doc  ───┘└─────┘   └─────────────┘└─
txt  ───┘└─────┘   └─────────────┘└─
par  ───┘└─────┘   └─────────────┘└─
pid  ──────────┘   └────────────────
st   ────────────────────────────┘└─
1238      { unfold stmts₁ at h₀₁, exact h₀₁ },
id                                     └─┘
src  ─────┘└──────────────────┘└┘└────┘   └──
typ  ─────┘└──────────────────┘└┘└────┘└─┘└──
doc  ─────┘└──────────────────┘└┘└────┘   └──
txt  ─────┘└──────────────────┘└┘└────┘   └──
par  ─────┘└──────────────────┘└┘└────┘   └──
pid  ─────────────────────────────────┘   └───
st   ────┘└───────────────────┘└──────────┘└─
1239      { exact finset.mem_insert_of_mem (IH h₁₂) } },
id               └──────────────────────┘  └┘ └─┘
src  ─────┘└────┘└──────────────────────┘      └┘└─┘
typ  ─────┘└────┘└──────────────────────┘ └┘└─┘└┘└─┘
doc  ─────┘└────┘                              └┘└─┘
txt  ─────┘└────┘                              └┘└─┘
par  ─────┘└────┘                              └┘└─┘
pid  ───────────┘                              └───┘
st   ────┘└───────────────────────────────────────┘└─┘
1240    case TM2.stmt.branch : f q₁ q₂ IH₁ IH₂ {
src    └────────────────────────────────────────
typ    └────────────────────────────────────────
doc    └────────────────────────────────────────
txt    └────────────────────────────────────────
par    └────────────────────────────────────────
pid        └──────────────┘└────────────────┘└──
st   ─────────────────────────────────────────┘
1241      rcases h₁₂ with rfl | h₁₂ | h₁₂,
id              └─┘
src  ───┘└─────┘   └───────────────────┘└─
typ  ───┘└─────┘└─┘└───────────────────┘└─
doc  ───┘└─────┘   └───────────────────┘└─
txt  ───┘└─────┘   └───────────────────┘└─
par  ───┘└─────┘   └───────────────────┘└─
pid  ──────────┘   └──────────────────────
st   ──────────────────────────────────┘└─
1242      { unfold stmts₁ at h₀₁, exact h₀₁ },
id                                     └─┘
src  ─────┘└──────────────────┘└┘└────┘   └──
typ  ─────┘└──────────────────┘└┘└────┘└─┘└──
doc  ─────┘└──────────────────┘└┘└────┘   └──
txt  ─────┘└──────────────────┘└┘└────┘   └──
par  ─────┘└──────────────────┘└┘└────┘   └──
pid  ─────────────────────────────────┘   └───
st   ────┘└───────────────────┘└──────────┘└─
1243      { exact finset.mem_insert_of_mem (finset.mem_union_left _ (IH₁ h₁₂)) },
id               └──────────────────────┘  └───────────────────┘    └─┘ └─┘
src  ─────┘└────┘└──────────────────────┘ └───────────────────┘└─┘       └─┘└──
typ  ─────┘└────┘└──────────────────────┘ └───────────────────┘└─┘ └─┘└─┘└─┘└──
doc  ─────┘└────┘                                              └─┘       └─┘└──
txt  ─────┘└────┘                                              └─┘       └─┘└──
par  ─────┘└────┘                                              └─┘       └─┘└──
pid  ───────────┘                                              └─┘       └─────
st   ────┘└──────────────────────────────────────────────────────────────────┘└─
1244      { exact finset.mem_insert_of_mem (finset.mem_union_right _ (IH₂ h₁₂)) } },
id               └──────────────────────┘  └────────────────────┘    └─┘ └─┘
src  ─────┘└────┘└──────────────────────┘ └────────────────────┘└─┘       └─┘└─┘
typ  ─────┘└────┘└──────────────────────┘ └────────────────────┘└─┘ └─┘└─┘└─┘└─┘
doc  ─────┘└────┘                                               └─┘       └─┘└─┘
txt  ─────┘└────┘                                               └─┘       └─┘└─┘
par  ─────┘└────┘                                               └─┘       └─┘└─┘
pid  ───────────┘                                               └─┘       └────┘
st   ─────────────────────────────────────────────────────────────────────────┘└──┘
1245    case TM2.stmt.goto : l {
src    └────────────────────────
typ    └────────────────────────
doc    └────────────────────────
txt    └────────────────────────
par    └────────────────────────
pid        └────────────┘└──┘└──
st   ─────────────────────────┘
1246      subst h₁₂, exact h₀₁ },
id             └─┘        └─┘
src  ───┘└────┘   └┘└────┘   
typ  ───┘└────┘└─┘└┘└────┘└─┘
doc  ───┘└────┘   └┘└────┘   
txt  ───┘└────┘   └┘└────┘   
par  ───┘└────┘   └┘└────┘   
pid  ─────────┘   └──────┘   └┘
st   ────────────┘└──────────┘└┘
1247    case TM2.stmt.halt {
src    └────────────────────
typ    └────────────────────
doc    └────────────────────
txt    └────────────────────
par    └────────────────────
pid        └────────────┘└─
st   ───────────────────────
1248      subst h₁₂, exact h₀₁ }
id             └─┘        └─┘
src  ───┘└────┘   └┘└────┘   └┘
typ  ───┘└────┘└─┘└┘└────┘└─┘└┘
doc  ───┘└────┘   └┘└────┘   └┘
txt  ───┘└────┘   └┘└────┘   └┘
par  ───┘└────┘   └┘└────┘   └┘
pid  ─────────┘   └──────┘   └┘
st   ────────────┘└──────────┘
1249  end
st   └─┘
1250  
1251  theorem stmts₁_supports_stmt_mono {S q₁ q₂}
1252    (h : q₁ ∈ stmts₁ q₂) (hs : supports_stmt S q₂) : supports_stmt S q₁ :=
id          └┘  └────┘ └┘        └───────────┘  └┘    └───────────┘  └┘
src             └────┘           └───────────┘         └───────────┘
typ         └┘  └────┘ └┘        └───────────┘  └┘    └───────────┘  └┘
1253  begin
st   └─────
1254    induction q₂ with _ _ q IH _ _ q IH _ _ q IH _ q IH;
id               └┘
src    └────────┘  └─────────────────────────────────────┘
typ    └────────┘└┘└─────────────────────────────────────┘
doc    └────────┘  └─────────────────────────────────────┘
txt    └────────┘  └─────────────────────────────────────┘
par    └────────┘  └─────────────────────────────────────┘
pid               └────────────────────────────────────┘
st   ───────────────────────────────────────────────────────
1255      simp only [stmts₁, supports_stmt, finset.mem_insert, finset.mem_union,
id                  └────┘  └───────────┘  └───────────────┘  └──────────────┘
src      └─────────┘└────┘└┘└───────────┘└┘└───────────────┘└┘└──────────────┘└─
typ      └─────────┘└────┘└┘└───────────┘└┘└───────────────┘└┘└──────────────┘└─
doc      └─────────┘      └┘             └┘                 └┘                └─
txt      └─────────┘      └┘             └┘                 └┘                └─
par      └─────────┘      └┘             └┘                 └┘                └─
pid          └──┘└┘      └┘             └┘                 └┘                └─
st   ───────────────────────────────────────────────────────────────────────────
1256        finset.insert_empty_eq_singleton, finset.mem_singleton] at h hs,
id         └──────────────────────────────┘  └──────────────────┘
src  ─────┘└──────────────────────────────┘└┘└──────────────────┘└───────┘
typ  ─────┘└──────────────────────────────┘└┘└──────────────────┘└───────┘
doc  ─────┘                                └┘                    └───────┘
txt  ─────┘                                └┘                    └───────┘
par  ─────┘                                └┘                    └───────┘
pid  ─────┘                                └┘                    └─────┘
st   ────────────────────────────────────────────────────────────────────┘└─
1257    iterate 4 { rcases h with rfl | h; [exact hs, exact IH h hs] },
id                                              └┘        └┘  └┘
src    └──────────┘└─────┘ └───────────┘└─┘└────┘  └┘└────┘     └─┘
typ    └──────────┘└─────┘└───────────┘└─┘└────┘└┘└┘└────┘└┘└┘└─┘
doc    └──────────┘└─────┘ └───────────┘└─┘└────┘  └┘└────┘     └─┘
txt    └──────────┘└─────┘ └───────────┘└─┘└────┘  └┘└────┘     └─┘
par    └──────────┘└─────┘ └───────────┘└─┘└────┘  └┘└────┘     └─┘
pid           └─────────┘ └────────────────────┘  └──────┘     └─┘
st   ────────────┘└───────────────────────────────────────────────┘└─┘
1258    case TM2.stmt.branch : f q₁ q₂ IH₁ IH₂ {
src    └────────────────────────────────────────
typ    └────────────────────────────────────────
doc    └────────────────────────────────────────
txt    └────────────────────────────────────────
par    └────────────────────────────────────────
pid        └──────────────┘└────────────────┘└──
st   ─────────────────────────────────────────┘
1259      rcases h with rfl | h | h, exacts [hs, IH₁ h hs.1, IH₂ h hs.2] },
id                                         └┘  └─┘  └┘    └─┘  └┘
src  ───┘└─────┘ └───────────────┘└┘└──────┘  └┘      └──┘      └──┘
typ  ───┘└─────┘└───────────────┘└┘└──────┘└┘└┘└─┘└┘└──┘└─┘└┘└──┘
doc  ───┘└─────┘ └───────────────┘└┘└──────┘  └┘      └──┘      └──┘
txt  ───┘└─────┘ └───────────────┘└┘└──────┘  └┘      └──┘      └──┘
par  ───┘└─────┘ └───────────────┘└┘└──────┘  └┘      └──┘      └──┘
pid  ──────────┘ └─────────────────────────┘  └┘      └──┘      └───┘
st   ────────────────────────────┘└────────────────────────────────────┘└┘
1260    case TM2.stmt.goto : l { subst h, exact hs },
id                                            └┘
src    └───────────────────────┘└────┘ └┘└────┘  
typ    └───────────────────────┘└────┘└┘└────┘└┘
doc    └───────────────────────┘└────┘ └┘└────┘  
txt    └───────────────────────┘└────┘ └┘└────┘  
par    └───────────────────────┘└────┘ └┘└────┘  
pid        └────────────┘└──┘└───────┘ └──────┘  └┘
st   ─────────────────────────┘└──────┘└─────────┘└┘
1261    case TM2.stmt.halt { subst h, trivial }
id                                
src    └───────────────────┘└────┘ └┘└──────┘└┘
typ    └───────────────────┘└────┘└┘└──────┘└┘
doc    └───────────────────┘└────┘ └┘└──────┘└┘
txt    └───────────────────┘└────┘ └┘└──────┘└┘
par    └───────────────────┘└────┘ └┘└──────┘└┘
pid        └────────────┘└──────┘ └─────────┘
st   ─────────────────────────────┘└────────┘
1262  end
st   └─┘
1263  
1264  noncomputable def stmts
1265    (M : Λ → stmt) (S : finset Λ) : finset (option stmt) :=
id             └──┘       └────┘     └────┘  └────┘ └──┘
src             └──┘       └────┘      └────┘  └────┘ └──┘
typ            └──┘       └────┘     └────┘  └────┘ └──┘
doc             └──┘       └────┘      └────┘         └──┘
1266  (S.bind (λ q, stmts₁ (M q))).insert_none
id    └───┘      └────┘      └─────────┘
src    └───┘       └────┘        └─────────┘
typ   └───┘      └────┘      └─────────┘
doc    └───┘
1267  
1268  theorem stmts_trans {M : Λ → stmt} {S q₁ q₂}
id                               └──┘
src                               └──┘
typ                              └──┘
doc                               └──┘
1269    (h₁ : q₁ ∈ stmts₁ q₂) : some q₂ ∈ stmts M S → some q₁ ∈ stmts M S :=
id           └┘  └────┘ └┘    └──┘ └┘  └───┘     └──┘ └┘  └───┘  
src              └────┘       └──┘     └───┘       └──┘     └───┘
typ          └┘  └────┘ └┘    └──┘ └┘  └───┘     └──┘ └┘  └───┘  
1270  by simp only [stmts, finset.mem_insert_none, finset.mem_bind,
id                 └───┘  └────────────────────┘  └─────────────┘
src     └─────────┘└───┘└┘└────────────────────┘└┘└─────────────┘└─
typ     └─────────┘└───┘└┘└────────────────────┘└┘└─────────────┘└─
doc     └─────────┘     └┘                      └┘               └─
txt     └─────────┘     └┘                      └┘               └─
par     └─────────┘     └┘                      └┘               └─
pid         └──┘└┘     └┘                      └┘               └─
st     └───────────────────────────────────────────────────────────
1271    option.mem_def, forall_eq', exists_imp_distrib];
id     └────────────┘  └────────┘  └────────────────┘
src  ─┘└────────────┘└┘└────────┘└┘└────────────────┘
typ  ─┘└────────────┘└┘└────────┘└┘└────────────────┘
doc  ─┘              └┘          └┘                  
txt  ─┘              └┘          └┘                  
par  ─┘              └┘          └┘                  
pid  ─┘              └┘          └┘                  
st   ───────────────────────────────────────────────────
1272  exact λ l ls h₂, ⟨_, ls, stmts₁_trans h₂ h₁⟩
id                            └──────────┘    └┘
src  └────┘ └────────┘ └─┘  └┘└──────────┘    └─
typ  └────┘ └────────┘ └─┘  └┘└──────────┘  └┘└─
doc  └────┘ └────────┘ └─┘  └┘                └─
txt  └────┘ └────────┘ └─┘  └┘                └─
par  └────┘ └────────┘ └─┘  └┘                └─
pid        └────────┘ └─┘  └┘                
st   ─────────────────────────────────────────────
1273  
src  
typ  
doc  
txt  
par  
pid  
st   
1274  theorem stmts_supports_stmt {M : Λ → stmt} {S q}
id                                       └──┘
src                                       └──┘
typ                                      └──┘
doc                                       └──┘
1275    (ss : supports M S) : some q ∈ stmts M S → supports_stmt S q :=
id           └──────┘      └──┘   └───┘     └───────────┘  
src          └──────┘        └──┘    └───┘       └───────────┘
typ          └──────┘      └──┘   └───┘     └───────────┘  
1276  by simp only [stmts, finset.mem_insert_none, finset.mem_bind,
id                 └───┘  └────────────────────┘  └─────────────┘
src     └─────────┘└───┘└┘└────────────────────┘└┘└─────────────┘└─
typ     └─────────┘└───┘└┘└────────────────────┘└┘└─────────────┘└─
doc     └─────────┘     └┘                      └┘               └─
txt     └─────────┘     └┘                      └┘               └─
par     └─────────┘     └┘                      └┘               └─
pid         └──┘└┘     └┘                      └┘               └─
st     └───────────────────────────────────────────────────────────
1277    option.mem_def, forall_eq', exists_imp_distrib];
id     └────────────┘  └────────┘  └────────────────┘
src  ─┘└────────────┘└┘└────────┘└┘└────────────────┘
typ  ─┘└────────────┘└┘└────────┘└┘└────────────────┘
doc  ─┘              └┘          └┘                  
txt  ─┘              └┘          └┘                  
par  ─┘              └┘          └┘                  
pid  ─┘              └┘          └┘                  
st   ───────────────────────────────────────────────────
1278  exact λ l ls h, stmts₁_supports_stmt_mono h (ss.2 _ ls)
id                   └───────────────────────┘    └┘
src  └────┘ └───────┘└───────────────────────┘    └───┘  └─
typ  └────┘ └───────┘└───────────────────────┘  └┘└───┘  └─
doc  └────┘ └───────┘                             └───┘  └─
txt  └────┘ └───────┘                             └───┘  └─
par  └────┘ └───────┘                             └───┘  └─
pid        └───────┘                             └───┘  
st   ────────────────────────────────────────────────────────
1279  
src  
typ  
doc  
txt  
par  
pid  
st   
1280  theorem step_supports (M : Λ → stmt) {S}
id                                 └──┘
src                                 └──┘
typ                                └──┘
doc                                 └──┘
1281    (ss : supports M S) : ∀ {c c' : cfg},
id           └──────┘               └─┘
src          └──────┘                  └─┘
typ          └──────┘               └─┘
1282    c' ∈ step M c → c.l ∈ S.insert_none → c'.l ∈ S.insert_none
id     └┘  └──┘     └┘  └──────────┘   └┘└┘  └──────────┘
src        └──┘        └┘   └──────────┘     └┘   └──────────┘
typ    └┘  └──┘     └┘  └──────────┘   └┘└┘  └──────────┘
1283  | ⟨some l₁, v, T⟩ c' h₁ h₂ := begin
id      └──┘
src     └──┘
typ     └──┘
st                                 └─────
1284    replace h₂ := ss.2 _ (finset.some_mem_insert_none.1 h₂),
id                   └┘      └─────────────────────────┘   └┘
src    └────────────┘  └───┘ └─────────────────────────┘└─┘  
typ    └────────────┘└┘└───┘ └─────────────────────────┘└─┘└┘
doc    └────────────┘  └───┘                            └─┘  
txt    └────────────┘  └───┘                            └─┘  
par    └────────────┘  └───┘                            └─┘  
pid           └─┘└─┘  └───┘                            └─┘  
st   ────────────────────────────────────────────────────────┘└─
1285    simp only [step, option.mem_def] at h₁, subst c',
id                └──┘  └────────────┘               └┘
src    └─────────┘└──┘└┘└────────────┘└─────┘  └────┘
typ    └─────────┘└──┘└┘└────────────┘└─────┘  └────┘└┘
doc    └─────────┘    └┘              └─────┘  └────┘
txt    └─────────┘    └┘              └─────┘  └────┘
par    └─────────┘    └┘              └─────┘  └────┘
pid        └──┘└┘    └┘              └───┘       
st   ───────────────────────────────────────┘└────────┘└─
1286    revert h₂, induction M l₁ with _ _ q IH _ _ q IH _ _ q IH _ q IH generalizing v T;
id                           └┘
src    └───────┘  └────────┘   └──────────────────────────────────────────────────────┘
typ    └───────┘  └────────┘└┘└──────────────────────────────────────────────────────┘
doc    └───────┘  └────────┘   └──────────────────────────────────────────────────────┘
txt    └───────┘  └────────┘   └──────────────────────────────────────────────────────┘
par    └───────┘  └────────┘   └──────────────────────────────────────────────────────┘
pid          └─┘              └────────────────────────────────────┘└───────────────┘
st   ──────────┘└─────────────────────────────────────────────────────────────────────────
1287      intro hs,
src      └──────┘
typ      └──────┘
doc      └──────┘
txt      └──────┘
par      └──────┘
pid           └─┘
st   ───────────┘└─
1288    iterate 4 { exact IH _ _ hs },
id                       └┘     └┘
src    └──────────┘└────┘  └───┘  
typ    └──────────┘└────┘└┘└───┘└┘
doc    └──────────┘└────┘  └───┘  
txt    └──────────┘└────┘  └───┘  
par    └──────────┘└────┘  └───┘  
pid           └────────┘  └───┘  └┘
st   ─────────────────────────────┘└┘
1289    case TM2.stmt.branch : p q₁' q₂' IH₁ IH₂ {
src    └──────────────────────────────────────────
typ    └──────────────────────────────────────────
doc    └──────────────────────────────────────────
txt    └──────────────────────────────────────────
par    └──────────────────────────────────────────
pid        └──────────────┘└──────────────────┘└──
st   ───────────────────────────────────────────┘
1290      unfold step_aux, cases p v,
id                               
src  ───┘└─────────────┘└┘└────┘  └─
typ  ───┘└─────────────┘└┘└────┘└─
doc  ───┘└─────────────┘└┘└────┘  └─
txt  ───┘└─────────────┘└┘└────┘  └─
par  ───┘└─────────────┘└┘└────┘  └─
pid  ──────────────────────────┘  └─
st   ──────────────────┘└─────────┘└─
1291      { exact IH₂ _ _ hs.2 },
id               └─┘     └┘
src  ─────┘└────┘   └───┘  └─┘└──
typ  ─────┘└────┘└─┘└───┘└┘└─┘└──
doc  ─────┘└────┘   └───┘  └─┘└──
txt  ─────┘└────┘   └───┘  └─┘└──
par  ─────┘└────┘   └───┘  └─┘└──
pid  ───────────┘   └───┘  └─────
st   ────┘└──────────────────┘└─
1292      { exact IH₁ _ _ hs.1 } },
id               └─┘     └┘
src  ─────┘└────┘   └───┘  └─┘└─┘
typ  ─────┘└────┘└─┘└───┘└┘└─┘└─┘
doc  ─────┘└────┘   └───┘  └─┘└─┘
txt  ─────┘└────┘   └───┘  └─┘└─┘
par  ─────┘└────┘   └───┘  └─┘└─┘
pid  ───────────┘   └───┘  └────┘
st   ────────────────────────┘└──┘
1293    case TM2.stmt.goto { exact finset.some_mem_insert_none.2 (hs _) },
id                                └─────────────────────────┘    └┘
src    └───────────────────┘└────┘└─────────────────────────┘└─┘   └──┘
typ    └───────────────────┘└────┘└─────────────────────────┘└─┘ └┘└──┘
doc    └───────────────────┘└────┘                           └─┘   └──┘
txt    └───────────────────┘└────┘                           └─┘   └──┘
par    └───────────────────┘└────┘                           └─┘   └──┘
pid        └────────────┘└──────┘                           └─┘   └───┘
st   ─────────────────────┘└──────────────────────────────────────────┘└┘
1294    case TM2.stmt.halt { apply multiset.mem_cons_self }
id                                └────────────────────┘
src    └───────────────────┘└────┘└────────────────────┘└┘
typ    └───────────────────┘└────┘└────────────────────┘└┘
doc    └───────────────────┘└────┘                      └┘
txt    └───────────────────┘└────┘                      └┘
par    └───────────────────┘└────┘                      └┘
pid        └────────────┘└──────┘                      └┘
st   ───────────────────────────────────────────────────┘
1295  end
st   └─┘
1296  
1297  end
1298  
1299  end TM2
1300  
1301  namespace TM2to1
1302  
1303  section
1304  parameters {K : Type*} [decidable_eq K]
id                         └──────────┘
src                          └──────────┘
typ                        └──────────┘
1305  parameters {Γ : K → Type*}
id              
typ             
1306  parameters {Λ : Type*} [inhabited Λ]
id                          └───────┘
src                          └───────┘
typ                         └───────┘
1307  parameters {σ : Type*} [inhabited σ]
id                          └───────┘
src                          └───────┘
typ                         └───────┘
1308  
1309  local notation `stmt₂` := TM2.stmt Γ Λ σ
id                             └──────┘
src                            └──────┘
typ                            └──────┘
doc                            └──────┘
1310  local notation `cfg₂` := TM2.cfg Γ Λ σ
id                            └─────┘
src                           └─────┘
typ                           └─────┘
1311  
1312  inductive stackel (k : K)
id                          
typ                         
1313  | val : Γ k → stackel
id           
typ          
1314  | bottom : stackel
1315  | top : stackel
1316  
1317  instance stackel.inhabited (k) : inhabited (stackel k) :=
id                                    └───────┘  └─────┘ 
src                                   └───────┘  └─────┘
typ                                   └───────┘  └─────┘ 
1318  ⟨stackel.top _⟩
id    └─────────┘
src   └─────────┘
typ   └─────────┘
1319  
1320  def stackel.is_bottom {k} : stackel k → bool
id                               └─────┘   └──┘
src                              └─────┘     └──┘
typ                              └─────┘   └──┘
1321  | (stackel.bottom _) := tt
id      └────────────┘       └┘
src     └────────────┘       └┘
typ     └────────────┘       └┘
1322  | _ := ff
id          └┘
src         └┘
typ         └┘
1323  
1324  def stackel.is_top {k} : stackel k → bool
id                            └─────┘   └──┘
src                           └─────┘     └──┘
typ                           └─────┘   └──┘
1325  | (stackel.top _) := tt
id      └─────────┘       └┘
src     └─────────┘       └┘
typ     └─────────┘       └┘
1326  | _ := ff
id          └┘
src         └┘
typ         └┘
1327  
1328  def stackel.get {k} : stackel k → option (Γ k)
id                         └─────┘   └────┘   
src                        └─────┘     └────┘
typ                        └─────┘   └────┘   
1329  | (stackel.val a) := some a
id      └─────────┘      └──┘
src     └─────────┘       └──┘
typ     └─────────┘      └──┘
1330  | _ := none
id          └──┘
src         └──┘
typ         └──┘
1331  
1332  section
1333  open stackel
1334  
1335  def stackel_equiv {k} : stackel k ≃ option (option (Γ k)) :=
id                           └─────┘   └────┘  └────┘   
src                          └─────┘    └────┘  └────┘
typ                          └─────┘   └────┘  └────┘   
doc                                    
1336  begin
st   └─────
1337    refine ⟨λ s, _, λ s, _, _, _⟩,
src    └─────┘  └─────┘ └──────────┘
typ    └─────┘  └─────┘ └──────────┘
doc    └─────┘  └─────┘ └──────────┘
txt    └─────┘  └─────┘ └──────────┘
par    └─────┘  └─────┘ └──────────┘
pid            └─────┘ └──────────┘
st   ──────────────────────────────┘└─
1338    { cases s, exacts [some (some s), none, some none] },
id                             └──┘    └──┘  └──┘ └──┘
src      └────┘   └──────┘     └──┘ └─┘└──┘└┘└──┘└──┘└┘
typ      └────┘  └──────┘     └──┘└─┘└──┘└┘└──┘└──┘└┘
doc      └────┘   └──────┘          └─┘    └┘        └┘
txt      └────┘   └──────┘          └─┘    └┘        └┘
par      └────┘   └──────┘          └─┘    └┘        └┘
pid                    └┘          └─┘    └┘        
st   ───┘└─────┘└────────────────────────────────────────┘└┘
1339    { rcases s with _|_|s, exacts [bottom _, top _, val s] },
id                                                        
src      └─────┘ └─────────┘  └──────┘      └──┘   └──┘    └┘
typ      └─────┘└─────────┘  └──────┘      └──┘   └──┘   └┘
doc      └─────┘ └─────────┘  └──────┘      └──┘   └──┘    └┘
txt      └─────┘ └─────────┘  └──────┘      └──┘   └──┘    └┘
par      └─────┘ └─────────┘  └──────┘      └──┘   └──┘    └┘
pid             └─────────┘        └┘      └──┘   └──┘    
st   ───┘└─────────────────┘└────────────────────────────────┘└┘
1340    { intro s, cases s; refl },
id                      
src      └─────┘  └────┘   └───┘
typ      └─────┘  └────┘  └───┘
doc      └─────┘  └────┘   └───┘
txt      └─────┘  └────┘   └───┘
par      └─────┘  └────┘   └───┘
pid           └┘              
st   ───┘└─────┘└──────────────┘└┘
1341    { intro s, rcases s with _|_|s; refl },
id                       
src      └─────┘  └─────┘ └─────────┘  └───┘
typ      └─────┘  └─────┘└─────────┘  └───┘
doc      └─────┘  └─────┘ └─────────┘  └───┘
txt      └─────┘  └─────┘ └─────────┘  └───┘
par      └─────┘  └─────┘ └─────────┘  └───┘
pid           └┘         └─────────┘      
st   ──────────┘└──────────────────────────┘└──
1342  end
st   ──┘
1343  
1344  end
1345  
1346  def Γ' := ∀ k, stackel k
id                 └─────┘ 
src                 └─────┘
typ                └─────┘ 
1347  
1348  instance Γ'.inhabited : inhabited Γ' := ⟨λ _, default _⟩
id                           └───────┘ └┘         └─────┘
src                          └───────┘ └┘          └─────┘
typ                          └───────┘ └┘         └─────┘
1349  
1350  instance stackel.fintype {k} [fintype (Γ k)] : fintype (stackel k) :=
id                                 └─────┘        └─────┘  └─────┘ 
src                                └─────┘          └─────┘  └─────┘
typ                                └─────┘        └─────┘  └─────┘ 
doc                                └─────┘          └─────┘
1351  fintype.of_equiv _ stackel_equiv.symm
id   └──────────────┘   └───────────┘└───┘
src  └──────────────┘   └───────────┘└───┘
typ  └──────────────┘   └───────────┘└───┘
doc  └──────────────┘
1352  
1353  instance Γ'.fintype [fintype K] [∀ k, fintype (Γ k)] : fintype Γ' :=
id                        └─────┘        └─────┘        └─────┘ └┘
src                       └─────┘          └─────┘          └─────┘ └┘
typ                       └─────┘        └─────┘        └─────┘ └┘
doc                       └─────┘          └─────┘          └─────┘
1354  pi.fintype
id   └────────┘
src  └────────┘
typ  └────────┘
1355  
1356  inductive st_act (k : K)
id                         
typ                        
1357  | push {} : (σ → Γ k) → st_act
id                  
typ                 
1358  | pop {} : bool → (σ → option (Γ k) → σ) → st_act
id              └──┘       └────┘
src             └──┘        └────┘
typ             └──┘       └────┘
1359  
1360  section
1361  open st_act
1362  
1363  instance st_act.inhabited {k} : inhabited (st_act k) :=
id                                   └───────┘  └────┘ 
src                                  └───────┘  └────┘
typ                                  └───────┘  └────┘ 
1364  ⟨pop (default _) (λ s _, s)⟩
id    └─┘  └─────┘          
src   └─┘  └─────┘
typ   └─┘  └─────┘          
1365  
1366  def st_run {k : K} : st_act k → stmt₂ → stmt₂
id                       └────┘   └───┘   └───┘
src                       └────┘     └───┘   └───┘
typ                      └────┘   └───┘   └───┘
doc                                  └───┘   └───┘
1367  | (push f)   := TM2.stmt.push k f
id      └──┘        └───────────┘ 
src     └──┘         └───────────┘
typ     └──┘        └───────────┘ 
1368  | (pop ff f) := TM2.stmt.peek k f
id      └─┘ └┘      └───────────┘ 
src     └─┘ └┘       └───────────┘
typ     └─┘ └┘      └───────────┘ 
1369  | (pop tt f) := TM2.stmt.pop k f
id      └─┘ └┘      └──────────┘ 
src     └─┘ └┘       └──────────┘
typ     └─┘ └┘      └──────────┘ 
1370  
1371  def st_var {k : K} (v : σ) (l : list (Γ k)) : st_act k → σ
id                                 └──┘        └────┘   
src                                  └──┘          └────┘
typ                                └──┘        └────┘   
1372  | (push f)  := v
id      └──┘        
src     └──┘
typ     └──┘        
1373  | (pop b f) := f v l.head'
id      └─┘           └────┘
src     └─┘              └────┘
typ     └─┘           └────┘
1374  
1375  def st_write {k : K} (v : σ) (l : list (Γ k)) : st_act k → list (Γ k)
id                                   └──┘        └────┘   └──┘   
src                                    └──┘          └────┘     └──┘
typ                                  └──┘        └────┘   └──┘   
1376  | (push f) := f v :: l
id      └──┘         └┘ 
src     └──┘           └┘
typ     └──┘         └┘ 
1377  | (pop ff f) := l
id      └─┘ └┘       
src     └─┘ └┘
typ     └─┘ └┘       
1378  | (pop tt f) := l.tail
id      └─┘ └┘       └───┘
src     └─┘ └┘        └───┘
typ     └─┘ └┘       └───┘
1379  
1380  @[elab_as_eliminator] def {l} stmt_st_rec
doc    └────────────────┘
1381    {C : stmt₂ → Sort l}
id          └───┘
src         └───┘
typ         └───┘
doc         └───┘
1382    (H₁ : Π k (s : st_act k) q (IH : C q), C (st_run s q))
id                   └────┘                └────┘  
src                   └────┘                     └────┘
typ                  └────┘                └────┘  
1383    (H₂ : Π a q (IH : C q), C (TM2.stmt.load a q))
id                           └───────────┘  
src                               └───────────┘
typ                          └───────────┘  
1384    (H₃ : Π p q₁ q₂ (IH₁ : C q₁) (IH₂ : C q₂), C (TM2.stmt.branch p q₁ q₂))
id              └┘ └┘         └┘          └┘     └─────────────┘  └┘ └┘
src                                                  └─────────────┘
typ             └┘ └┘         └┘          └┘     └─────────────┘  └┘ └┘
1385    (H₄ : Π l, C (TM2.stmt.goto l))
id                 └───────────┘ 
src                  └───────────┘
typ                └───────────┘ 
1386    (H₅ : C TM2.stmt.halt) : ∀ n, C n
id            └───────────┘         
src            └───────────┘
typ           └───────────┘         
1387  | (TM2.stmt.push k f q)     := H₁ _ (push f) _ (stmt_st_rec q)
id      └───────────┘             └┘    └──┘       └─────────┘
src     └───────────┘                     └──┘
typ     └───────────┘             └┘    └──┘       └─────────┘
1388  | (TM2.stmt.peek k f q)     := H₁ _ (pop ff f) _ (stmt_st_rec q)
id      └───────────┘             └┘    └─┘ └┘       └─────────┘
src     └───────────┘                     └─┘ └┘
typ     └───────────┘             └┘    └─┘ └┘       └─────────┘
1389  | (TM2.stmt.pop k f q)      := H₁ _ (pop tt f) _ (stmt_st_rec q)
id      └──────────┘              └┘    └─┘ └┘       └─────────┘
src     └──────────┘                      └─┘ └┘
typ     └──────────┘              └┘    └─┘ └┘       └─────────┘
1390  | (TM2.stmt.load a q)       := H₂ _ _ (stmt_st_rec q)
id      └───────────┘              └┘      └─────────┘
src     └───────────┘
typ     └───────────┘              └┘      └─────────┘
1391  | (TM2.stmt.branch a q₁ q₂) := H₃ _ _ _ (stmt_st_rec q₁) (stmt_st_rec q₂)
id      └─────────────┘   └┘ └┘     └┘        └─────────┘      └─────────┘
src     └─────────────┘
typ     └─────────────┘   └┘ └┘     └┘        └─────────┘      └─────────┘
1392  | (TM2.stmt.goto l)         := H₄ _
id      └───────────┘               └┘
src     └───────────┘
typ     └───────────┘               └┘
1393  | TM2.stmt.halt             := H₅
id     └───────────┘                └┘
src    └───────────┘
typ    └───────────┘                └┘
1394  
1395  theorem supports_run [fintype K] [∀ k, fintype (Γ k)] [fintype σ]
id                         └─────┘        └─────┘       └─────┘ 
src                        └─────┘          └─────┘         └─────┘
typ                        └─────┘        └─────┘       └─────┘ 
doc                        └─────┘          └─────┘         └─────┘
1396    (S : finset Λ) {k} (s : st_act k) (q) :
id          └────┘            └────┘ 
src         └────┘             └────┘
typ         └────┘            └────┘ 
doc         └────┘
1397    TM2.supports_stmt S (st_run s q) ↔ TM2.supports_stmt S q :=
id     └───────────────┘   └────┘     └───────────────┘  
src    └───────────────┘    └────┘       └───────────────┘
typ    └───────────────┘   └────┘     └───────────────┘  
1398  by rcases s with _|_|_; refl
id             
src     └─────┘ └─────────┘  └────
typ     └─────┘└─────────┘  └────
doc     └─────┘ └─────────┘  └────
txt     └─────┘ └─────────┘  └────
par     └─────┘ └─────────┘  └────
pid            └─────────┘      
st     └──────────────────────────
1399  
src  
typ  
doc  
txt  
par  
pid  
st   
1400  end
1401  
1402  inductive Λ' : Type (max u_1 u_2 u_3 u_4)
1403  | normal {} : Λ → Λ'
1404  | go (k) : st_act k → stmt₂ → Λ'
id             └────┘    └───┘
src             └────┘     └───┘
typ            └────┘    └───┘
doc                        └───┘
1405  | ret {} : K → stmt₂ → Λ'
id                  └───┘
src                 └───┘
typ                 └───┘
doc                 └───┘
1406  open Λ'
1407  instance : inhabited Λ' := ⟨normal (default _)⟩
id              └───────┘ └┘     └────┘  └─────┘
src             └───────┘ └┘     └────┘  └─────┘
typ             └───────┘ └┘     └────┘  └─────┘
1408  
1409  local notation `stmt₁` := TM1.stmt Γ' Λ' σ
id                             └──────┘
src                            └──────┘
typ                            └──────┘
doc                            └──────┘
1410  local notation `cfg₁` := TM1.cfg Γ' Λ' σ
id                            └─────┘
src                           └─────┘
typ                           └─────┘
doc                           └─────┘
1411  
1412  open TM1.stmt
1413  
1414  def tr_st_act {k} (q : stmt₁) : st_act k → stmt₁
id                          └───┘    └────┘   └───┘
src                         └───┘    └────┘     └───┘
typ                         └───┘    └────┘   └───┘
doc                         └───┘               └───┘
1415  | (st_act.push f) :=
id      └─────────┘ 
src     └─────────┘
typ     └─────────┘ 
1416    write (λ a s, dwrite a k $ stackel.val $ f s) $
id     └───┘       └────┘     └─────────┘     
src    └───┘         └────┘       └─────────┘
typ    └───┘       └────┘     └─────────┘     
1417    move dir.right $
id     └──┘ └───────┘
src    └──┘ └───────┘
typ    └──┘ └───────┘
1418    write (λ a s, dwrite a k $ stackel.top k) q
id     └───┘       └────┘     └─────────┘   
src    └───┘         └────┘       └─────────┘
typ    └───┘       └────┘     └─────────┘   
1419  | (st_act.pop b f) :=
id      └────────┘  
src     └────────┘
typ     └────────┘  
1420    move dir.left $
id     └──┘ └──────┘
src    └──┘ └──────┘
typ    └──┘ └──────┘
1421    load (λ a s, f s (a k).get) $
id     └──┘             └─┘
src    └──┘                  └─┘
typ    └──┘             └─┘
1422    cond b
id     └──┘
src    └──┘
typ    └──┘
1423    ( branch (λ a s, (a k).is_bottom)
id       └────┘          └───────┘
src      └────┘              └───────┘
typ      └────┘          └───────┘
1424      ( move dir.right q )
id         └──┘ └───────┘ 
src        └──┘ └───────┘
typ        └──┘ └───────┘ 
1425      ( move dir.right $
id         └──┘ └───────┘
src        └──┘ └───────┘
typ        └──┘ └───────┘
1426        write (λ a s, dwrite a k $ default _) $
id         └───┘       └────┘     └─────┘
src        └───┘         └────┘       └─────┘
typ        └───┘       └────┘     └─────┘
1427        move dir.left $
id         └──┘ └──────┘
src        └──┘ └──────┘
typ        └──┘ └──────┘
1428        write (λ a s, dwrite a k $ stackel.top k) q ) )
id         └───┘       └────┘     └─────────┘   
src        └───┘         └────┘       └─────────┘
typ        └───┘       └────┘     └─────────┘   
1429    ( move dir.right q )
id       └──┘ └───────┘ 
src      └──┘ └───────┘
typ      └──┘ └───────┘ 
1430  
1431  def tr_init (k) (L : list (Γ k)) : list Γ' :=
id                        └──┘        └──┘ └┘
src                       └──┘          └──┘ └┘
typ                       └──┘        └──┘ └┘
1432  stackel.bottom :: match L.reverse with
id   └────────────┘ └┘       └──────┘
src  └────────────┘ └┘        └──────┘
typ  └────────────┘ └┘       └──────┘
1433  | [] := [stackel.top]
id     └┘    └─────────┘
src    └┘    └─────────┘
typ    └┘    └─────────┘
1434  | (a::L') := dwrite stackel.top k (stackel.val a) ::
id      └┘└┘     └────┘ └─────────┘   └─────────┘    └┘
src      └┘       └────┘ └─────────┘    └─────────┘    └┘
typ     └┘└┘     └────┘ └─────────┘   └─────────┘    └┘
1435    (L'.map stackel.val ++ [stackel.top k]).map (dwrite (default _) k)
id        └──┘ └─────────┘ └┘ └─────────┘  └─┘   └────┘  └─────┘    
src       └──┘ └─────────┘ └┘ └─────────┘   └─┘   └────┘  └─────┘
typ       └──┘ └─────────┘ └┘ └─────────┘  └─┘   └────┘  └─────┘    
1436  end
1437  
1438  theorem step_run {k : K} (q v S) : ∀ s : st_act k,
id                                          └────┘ 
src                                           └────┘
typ                                         └────┘ 
1439    TM2.step_aux (st_run s q) v S =
id     └──────────┘  └────┘      
src    └──────────┘  └────┘          
typ    └──────────┘  └────┘      
1440    TM2.step_aux q (st_var v (S k) s) (dwrite S k (st_write v (S k) s))
id     └──────────┘   └────┘         └────┘    └──────┘      
src    └──────────┘    └────┘             └────┘      └──────┘
typ    └──────────┘   └────┘         └────┘    └──────┘      
1441  | (st_act.push f) := rfl
id      └─────────┘       └─┘
src     └─────────┘       └─┘
typ     └─────────┘       └─┘
1442  | (st_act.pop ff f) := by unfold st_write; rw dwrite_self; refl
id      └────────┘ └┘                              └─────────┘
src     └────────┘ └┘          └─────────────┘  └─┘└─────────┘  └───┘
typ     └────────┘ └┘          └─────────────┘  └─┘└─────────┘  └───┘
doc                            └─────────────┘  └─┘             └───┘
txt                            └─────────────┘  └─┘             └───┘
par                            └─────────────┘  └─┘             └───┘
pid                                  └───────┘                     
st                            └───────────────────┘└─────────┘└─────┘
1443  | (st_act.pop tt f) := rfl
id      └────────┘ └┘       └─┘
src     └────────┘ └┘       └─┘
typ     └────────┘ └┘       └─┘
1444  
1445  def tr_normal : stmt₂ → stmt₁
id                   └───┘  └───┘
src                  └───┘   └───┘
typ                  └───┘  └───┘
doc                  └───┘   └───┘
1446  | (TM2.stmt.push k f q)     := goto (λ _ _, go k (st_act.push f) q)
id      └───────────┘            └──┘       └┘    └─────────┘
src     └───────────┘               └──┘         └┘    └─────────┘
typ     └───────────┘            └──┘       └┘    └─────────┘
1447  | (TM2.stmt.peek k f q)     := goto (λ _ _, go k (st_act.pop ff f) q)
id      └───────────┘            └──┘       └┘    └────────┘ └┘
src     └───────────┘               └──┘         └┘    └────────┘ └┘
typ     └───────────┘            └──┘       └┘    └────────┘ └┘
1448  | (TM2.stmt.pop k f q)      := goto (λ _ _, go k (st_act.pop tt f) q)
id      └──────────┘             └──┘       └┘    └────────┘ └┘
src     └──────────┘                └──┘         └┘    └────────┘ └┘
typ     └──────────┘             └──┘       └┘    └────────┘ └┘
1449  | (TM2.stmt.load a q)       := load (λ _, a) (tr_normal q)
id      └───────────┘             └──┘          └───────┘
src     └───────────┘               └──┘
typ     └───────────┘             └──┘          └───────┘
1450  | (TM2.stmt.branch f q₁ q₂) := branch (λ a, f) (tr_normal q₁) (tr_normal q₂)
id      └─────────────┘  └┘ └┘     └────┘          └───────┘      └───────┘
src     └─────────────┘             └────┘
typ     └─────────────┘  └┘ └┘     └────┘          └───────┘      └───────┘
1451  | (TM2.stmt.goto l)         := goto (λ a s, normal (l s))
id      └───────────┘              └──┘       └────┘    
src     └───────────┘               └──┘         └────┘
typ     └───────────┘              └──┘       └────┘    
1452  | TM2.stmt.halt             := halt
id     └───────────┘                └──┘
src    └───────────┘                └──┘
typ    └───────────┘                └──┘
1453  
1454  theorem tr_normal_run {k} (s q) :
1455    tr_normal (st_run s q) = goto (λ _ _, go k s q) :=
id     └───────┘  └────┘     └──┘       └┘   
src    └───────┘  └────┘       └──┘         └┘
typ    └───────┘  └────┘     └──┘       └┘   
1456  by rcases s with _|_|_; refl
id             
src     └─────┘ └─────────┘  └────
typ     └─────┘└─────────┘  └────
doc     └─────┘ └─────────┘  └────
txt     └─────┘ └─────────┘  └────
par     └─────┘ └─────────┘  └────
pid            └─────────┘      
st     └──────────────────────────
1457  
src  
typ  
doc  
txt  
par  
pid  
st   
1458  parameters (M : Λ → stmt₂)
id                       └───┘
src                      └───┘
typ                      └───┘
doc                      └───┘
1459  include M
1460  
1461  def tr : Λ' → stmt₁
id            └┘  └───┘
src           └┘   └───┘
typ           └┘  └───┘
doc                └───┘
1462  | (normal q) := tr_normal (M q)
id      └────┘      └───────┘  
src     └────┘       └───────┘
typ     └────┘      └───────┘  
1463  | (go k s q) :=
id      └┘   
src     └┘
typ     └┘   
1464    branch (λ a s, (a k).is_top) (tr_st_act (goto (λ _ _, ret k q)) s)
id     └────┘           └────┘    └───────┘  └──┘       └─┘
src    └────┘              └────┘    └───────┘  └──┘         └─┘
typ    └────┘           └────┘    └───────┘  └──┘       └─┘
1465      (move dir.right $ goto (λ _ _, go k s q))
id        └──┘ └───────┘   └──┘       └┘
src       └──┘ └───────┘   └──┘         └┘
typ       └──┘ └───────┘   └──┘       └┘
1466  | (ret k q) :=
id      └─┘  
src     └─┘
typ     └─┘  
1467    branch (λ a s, (a k).is_bottom) (tr_normal q)
id     └────┘           └───────┘    └───────┘
src    └────┘              └───────┘    └───────┘
typ    └────┘           └───────┘    └───────┘
1468      (move dir.left $ goto (λ _ _, ret k q))
id        └──┘ └──────┘   └──┘       └─┘
src       └──┘ └──────┘   └──┘         └─┘
typ       └──┘ └──────┘   └──┘       └─┘
1469  
1470  def tr_stk {k} (S : list (Γ k)) (L : list (stackel k)) : Prop :=
id                       └──┘           └──┘  └─────┘ 
src                      └──┘             └──┘  └─────┘
typ                      └──┘           └──┘  └─────┘ 
1471  ∃ n, L = (S.map stackel.val).reverse_core (stackel.top k :: list.repeat (default _) n)
id        └──┘ └─────────┘ └──────────┘   └─────────┘  └┘ └─────────┘  └─────┘    
src          └──┘ └─────────┘ └──────────┘   └─────────┘   └┘ └─────────┘  └─────┘
typ       └──┘ └─────────┘ └──────────┘   └─────────┘  └┘ └─────────┘  └─────┘    
1472  
1473  local attribute [pp_using_anonymous_constructor] turing.TM1.cfg
id                                                    └────────────┘
src                                                   └────────────┘
typ                                                   └────────────┘
doc                   └────────────────────────────┘  └────────────┘
1474  inductive tr_cfg : cfg₂ → cfg₁ → Prop
id                      └──┘   └──┘
src                     └──┘   └──┘
typ                     └──┘   └──┘
doc                            └──┘
1475  | mk {q v} {S : ∀ k, list (Γ k)} {L : list Γ'} :
id                     └──┘            └──┘ └┘
src                       └──┘             └──┘ └┘
typ                    └──┘            └──┘ └┘
1476    (∀ k, tr_stk (S k) (L.map (λ a, a k))) →
id          └────┘      └──┘       
src          └────┘         └──┘
typ         └────┘      └──┘       
1477    tr_cfg ⟨q, v, S⟩ ⟨q.map normal, v, (stackel.bottom, [], L)⟩
id                    └──┘ └────┘    └────────────┘  └┘  
src                       └──┘ └────┘     └────────────┘  └┘
typ                   └──┘ └────┘    └────────────┘  └┘  
1478  
1479  theorem tr_respects_aux₁ {k} (o q v) : ∀ S₁ {s S₂} {T : list Γ'},
id                                            └┘   └┘       └──┘ └┘
src                                                          └──┘ └┘
typ                                           └┘   └┘       └──┘ └┘
1480    T.map (λ (a : Γ'), a k) = (list.map stackel.val S₁).reverse_core (s :: S₂) →
id     └──┘         └┘        └──────┘ └─────────┘ └┘ └──────────┘    └┘ └┘
src     └──┘         └┘          └──────┘ └─────────┘    └──────────┘     └┘
typ    └──┘         └┘        └──────┘ └─────────┘ └┘ └──────────┘    └┘ └┘
1481    ∃ a T₁ T₂,
id       └┘ └┘
src            
typ      └┘ └┘
1482      T = list.reverse_core T₁ (a :: T₂) ∧
id         └───────────────┘ └┘   └┘ └┘  
src         └───────────────┘       └┘     
typ        └───────────────┘ └┘   └┘ └┘  
1483      a k = s ∧
id           
src             
typ          
1484      T₁.map (λ (a : Γ'), a k) = S₁.map stackel.val ∧
id       └┘└──┘         └┘       └┘└──┘ └─────────┘ 
src        └──┘         └┘           └──┘ └─────────┘ 
typ      └┘└──┘         └┘       └┘└──┘ └─────────┘ 
1485      T₂.map (λ (a : Γ'), a k) = S₂ ∧
id       └┘└──┘         └┘       └┘ 
src        └──┘         └┘            
typ      └┘└──┘         └┘       └┘ 
1486      reaches₀ (TM1.step tr)
id       └──────┘  └──────┘ └┘
src      └──────┘  └──────┘ └┘
typ      └──────┘  └──────┘ └┘
1487        ⟨some (go k o q), v, (stackel.bottom, [], T)⟩
id          └──┘  └┘        └────────────┘  └┘  
src         └──┘  └┘            └────────────┘  └┘
typ         └──┘  └┘        └────────────┘  └┘  
1488        ⟨some (go k o q), v, (a, T₁ ++ [stackel.bottom], T₂)⟩
id          └──┘  └┘          └┘ └┘ └────────────┘  └┘
src         └──┘  └┘                  └┘ └────────────┘
typ         └──┘  └┘          └┘ └┘ └────────────┘  └┘
1489  | [] s S₂ (a :: T) hT := by injection hT with es e₂; exact
id     └┘         └┘                       └┘
src    └┘         └┘             └────────┘  └─────────┘  └─────
typ    └┘         └┘             └────────┘└┘└─────────┘  └─────
doc                              └────────┘  └─────────┘  └─────
txt                              └────────┘  └─────────┘  └─────
par                              └────────┘  └─────────┘  └─────
pid                                         └─────────┘       
st                              └───────────────────────────────
1490    ⟨a, [], _, rfl, es, rfl, e₂, reaches₀.single rfl⟩
id                    └┘       └┘  └─────────────┘ └─┘
src  ─┘  └┘  └───┘   └┘  └┘   └┘  └┘└─────────────┘└─┘└┘
typ  ─┘ └┘  └───┘   └┘└┘└┘   └┘└┘└┘└─────────────┘└─┘└┘
doc  ─┘  └┘  └───┘   └┘  └┘   └┘  └┘                  └┘
txt  ─┘  └┘  └───┘   └┘  └┘   └┘  └┘                  └┘
par  ─┘  └┘  └───┘   └┘  └┘   └┘  └┘                  └┘
pid  ─┘  └┘  └───┘   └┘  └┘   └┘  └┘                  
st   ───────────────────────────────────────────────────┘
1491  | (s' :: S₁) s S₂ T hT :=
id         └┘ └┘         └┘
src        └┘
typ        └┘ └┘         └┘
1492    let ⟨a, T₁, b'::T₂, e, es', e₁, e₂, H⟩ := tr_respects_aux₁ S₁ hT in
id     └─┘           └┘                          └──────────────┘
src                  └┘
typ    └─┘           └┘                          └──────────────┘
1493    by injection e₂ with es e₂; exact
id                  └┘
src       └────────┘  └─────────┘  └─────
typ       └────────┘└┘└─────────┘  └─────
doc       └────────┘  └─────────┘  └─────
txt       └────────┘  └─────────┘  └─────
par       └────────┘  └─────────┘  └─────
pid                  └─────────┘       
st       └───────────────────────────────
1494    ⟨b', a::T₁, T₂, e, es, congr (congr_arg list.cons es') e₁,
id      └┘    └┘  └┘    └┘  └───┘  └───────┘ └───────┘ └─┘  └┘
src  ─┘   └┘     └┘  └┘ └┘  └┘└───┘ └───────┘└───────┘   └┘  └─
typ  ─┘ └┘└┘  └┘└┘└┘└┘└┘└┘└┘└───┘ └───────┘└───────┘└─┘└┘└┘└─
doc  ─┘   └┘     └┘  └┘ └┘  └┘                           └┘  └─
txt  ─┘   └┘     └┘  └┘ └┘  └┘                           └┘  └─
par  ─┘   └┘     └┘  └┘ └┘  └┘                           └┘  └─
pid  ─┘   └┘     └┘  └┘ └┘  └┘                           └┘  └─
st   ─────────────────────────────────────────────────────────────
1495      e₂, H.tail (by unfold TM1.step;
id       └┘  └────┘
src  ───┘  └┘└────┘   └─────────────┘└─
typ  ───┘└┘└┘└────┘   └─────────────┘└─
doc  ───┘  └┘         └─────────────┘└─
txt  ───┘  └┘         └─────────────┘└─
par  ───┘  └┘         └─────────────┘└─
pid  ───┘  └┘         └─────────────────
st   ─────────────────┘└─────────────────
1496        change some (cond (TM2to1.stackel.is_top (a k)) _ _) = _;
id                └──┘  └──┘  └───────────────────┘           
src  ─────┘└─────┘└──┘ └──┘ └───────────────────┘   └──────┘└┘└─
typ  ─────┘└─────┘└──┘ └──┘ └───────────────────┘ └──────┘└┘└─
doc  ─────┘└─────┘                                  └──────┘ └┘└─
txt  ─────┘└─────┘                                  └──────┘ └┘└─
par  ─────┘└─────┘                                  └──────┘ └┘└─
pid  ────────────┘                                  └──────┘ └───
st   ────────────────────────────────────────────────────────────────
1497        rw es'; refl)⟩
id            └─┘
src  ─────┘└─┘   └┘└──┘└──
typ  ─────┘└─┘└─┘└┘└──┘└──
doc  ─────┘└─┘   └┘└──┘└──
txt  ─────┘└─┘   └┘└──┘└──
par  ─────┘└─┘   └┘└──┘└──
pid  ────────┘   └──────┘
st   ────────┘└─┘└────┘└──
1498  
src  
typ  
doc  
txt  
par  
pid  
st   
1499  local attribute [simp] TM1.step TM1.step_aux tr tr_st_act st_var st_write
id                          └──────┘ └──────────┘ └┘ └───────┘ └────┘ └──────┘
src                         └──────┘ └──────────┘ └┘ └───────┘ └────┘ └──────┘
typ                         └──────┘ └──────────┘ └┘ └───────┘ └────┘ └──────┘
doc                   └──┘           └──────────┘
1500    tape.move tape.write list.reverse_core stackel.get stackel.is_bottom
id     └───────┘ └────────┘ └───────────────┘ └─────────┘ └───────────────┘
src    └───────┘ └────────┘ └───────────────┘ └─────────┘ └───────────────┘
typ    └───────┘ └────────┘ └───────────────┘ └─────────┘ └───────────────┘
1501  
1502  theorem tr_respects_aux₂
1503    {k q v} {S : Π k, list (Γ k)} {T₁ T₂ : list Γ'} {a : Γ'}
id                      └──┘               └──┘ └┘       └┘
src                      └──┘                 └──┘ └┘       └┘
typ                     └──┘               └──┘ └┘       └┘
1504    (hT : ∀ k, tr_stk (S k) ((T₁.reverse_core (a :: T₂)).map (λ (a : Γ'), a k)))
id               └────┘       └┘└───────────┘   └┘ └┘  └─┘          └┘    
src               └────┘           └───────────┘    └┘     └─┘          └┘
typ              └────┘       └┘└───────────┘   └┘ └┘  └─┘          └┘    
1505    (e₁ : T₁.map (λ (a : Γ'), a k) = list.map stackel.val (S k))
id           └┘└──┘         └┘       └──────┘ └─────────┘   
src            └──┘         └┘         └──────┘ └─────────┘
typ          └┘└──┘         └┘       └──────┘ └─────────┘   
1506    (ea : a k = stackel.top k) (o) :
id              └─────────┘ 
src               └─────────┘
typ             └─────────┘ 
1507    let v' := st_var v (S k) o,
id         └┘    └────┘      
src              └────┘
typ        └┘    └────┘      
1508        Sk' := st_write v (S k) o,
id         └─┘    └──────┘      
src               └──────┘
typ        └─┘    └──────┘      
1509        S' : ∀ k, list (Γ k) := dwrite S k Sk' in
id                  └──┘        └────┘   └─┘
src                  └──┘          └────┘
typ                 └──┘        └────┘   └─┘
1510    ∃ b (T₁' T₂' : list Γ'),
id                  └──┘ └┘ 
src                  └──┘ └┘ 
typ                 └──┘ └┘ 
1511      (∀ (k' : K), tr_stk (S' k') ((T₁'.reverse_core (b :: T₂')).map (λ (a : Γ'), a k'))) ∧
id                   └────┘  └┘ └┘    └─┘└───────────┘   └┘ └─┘  └─┘          └┘    └┘    
src                   └────┘              └───────────┘    └┘      └─┘          └┘           
typ                  └────┘  └┘ └┘    └─┘└───────────┘   └┘ └─┘  └─┘          └┘    └┘    
1512      T₁'.map (λ a, a k) = Sk'.map stackel.val ∧
id       └─┘└──┘          └─┘└──┘ └─────────┘ 
src         └──┘                └──┘ └─────────┘ 
typ      └─┘└──┘          └─┘└──┘ └─────────┘ 
1513      b k = stackel.top k ∧
id          └─────────┘  
src           └─────────┘   
typ         └─────────┘  
1514      TM1.step_aux (tr_st_act q o) v (a, T₁ ++ [stackel.bottom], T₂) =
id       └──────────┘  └───────┘       └┘ └┘ └────────────┘  └┘  
src      └──────────┘  └───────┘              └┘ └────────────┘      
typ      └──────────┘  └───────┘       └┘ └┘ └────────────┘  └┘  
doc      └──────────┘
1515      TM1.step_aux q v' (b, T₁' ++ [stackel.bottom], T₂') :=
id       └──────────┘  └┘   └─┘ └┘ └────────────┘  └─┘
src      └──────────┘             └┘ └────────────┘
typ      └──────────┘  └┘   └─┘ └┘ └────────────┘  └─┘
doc      └──────────┘
1516  begin
st   └─────
1517    dsimp only,
src    └────────┘
typ    └────────┘
doc    └────────┘
txt    └────────┘
par    └────────┘
pid         └───┘
st   ───────────┘└─
1518    cases o with f b f,
id           
src    └────┘ └─────────┘
typ    └────┘└─────────┘
doc    └────┘ └─────────┘
txt    └────┘ └─────────┘
par    └────┘ └─────────┘
pid          └─────────┘
st   ───────────────────┘└─
1519    case TM2to1.st_act.push : {
src    └───────────────────────────
typ    └───────────────────────────
doc    └───────────────────────────
txt    └───────────────────────────
par    └───────────────────────────
pid        └─────────────────┘└┘└──
st   ────────────────────────────┘
1520      refine ⟨_, dwrite a k (stackel.val (f v)) :: T₁,
id                  └────┘                        └┘
src  ───┘└─────┘ └─┘└────┘                 └─┘    └─
typ  ───┘└─────┘ └─┘└────┘             └─┘  └┘└─
doc  ───┘└─────┘ └─┘                       └─┘    └─
txt  ───┘└─────┘ └─┘                       └─┘    └─
par  ───┘└─────┘ └─┘                       └─┘    └─
pid  ──────────┘ └─┘                       └─┘    └─
st   ─────────────────────────────────────────────────────
1521        _, _, by simp only [list.map, dwrite_eq, e₁]; refl,
id                             └──────┘  └───────┘  └┘
src  ───────────┘  └─────────┘└──────┘└┘└───────┘└┘  └┘└──┘└─
typ  ───────────┘  └─────────┘└──────┘└┘└───────┘└┘└┘└┘└──┘└─
doc  ───────────┘  └─────────┘        └┘         └┘  └┘└──┘└─
txt  ───────────┘  └─────────┘        └┘         └┘  └┘└──┘└─
par  ───────────┘  └─────────┘        └┘         └┘  └┘└──┘└─
pid  ───────────┘  └──────────┘        └┘         └┘  └────────
st   ─────────────┘└────────────────────────────────────────┘└─
1522        by simp only [tape.write, tape.move, dwrite_eq], rfl⟩,
id                       └────────┘  └───────┘  └───────┘   └─┘
src  ─────┘  └─────────┘└────────┘└┘└───────┘└┘└───────┘└┘└─┘└─
typ  ─────┘  └─────────┘└────────┘└┘└───────┘└┘└───────┘└┘└─┘└─
doc  ─────┘  └─────────┘          └┘         └┘         └┘   └─
txt  ─────┘  └─────────┘          └┘         └┘         └┘   └─
par  ─────┘  └─────────┘          └┘         └┘         └┘   └─
pid  ─────┘  └──────────┘          └┘         └┘         └─┘   └──
st   ───────┘└───────────────────────────────────────────┘└────┘└─
1523      intro k', cases hT k' with n e,
id                       └┘ └┘
src  ───┘└──────┘└┘└────┘    └───────┘└─
typ  ───┘└──────┘└┘└────┘└┘└┘└───────┘└─
doc  ───┘└──────┘└┘└────┘    └───────┘└─
txt  ───┘└──────┘└┘└────┘    └───────┘└─
par  ───┘└──────┘└┘└────┘    └───────┘└─
pid  ───────────────────┘    └──────────
st   ───────────┘└────────────────────┘└─
1524      by_cases h : k' = k,
id                    └┘  
src  ───┘└───────┘ └─┘   └─
typ  ───┘└───────┘ └─┘└┘└─
doc  ───┘└───────┘ └─┘    └─
txt  ───┘└───────┘ └─┘    └─
par  ───┘└───────┘ └─┘    └─
pid  ────────────┘ └─┘    └─
st   ──────────────────────┘└─
1525      { subst k', existsi n.pred,
id               └┘          └────┘
src  ─────┘└────┘  └┘└──────┘└────┘└─
typ  ─────┘└────┘└┘└┘└──────┘└────┘└─
doc  ─────┘└────┘  └┘└──────┘      └─
txt  ─────┘└────┘  └┘└──────┘      └─
par  ─────┘└────┘  └┘└──────┘      └─
pid  ───────────┘  └────────┘      └─
st   ────┘└───────┘└──────────────┘└─
1526        simp only [list.reverse_core_eq, list.map_append, list.map_reverse, e₁,
id                    └──────────────────┘  └─────────────┘  └──────────────┘  └┘
src  ─────┘└─────────┘└──────────────────┘└┘└─────────────┘└┘└──────────────┘└┘  └─
typ  ─────┘└─────────┘└──────────────────┘└┘└─────────────┘└┘└──────────────┘└┘└┘└─
doc  ─────┘└─────────┘                    └┘               └┘                └┘  └─
txt  ─────┘└─────────┘                    └┘               └┘                └┘  └─
par  ─────┘└─────────┘                    └┘               └┘                └┘  └─
pid  ────────────────┘                    └┘               └┘                └┘  └─
st   ──────────────────────────────────────────────────────────────────────────────
1527          list.map_cons, list.append_left_inj] at e,
id           └───────────┘  └──────────────────┘
src  ───────┘└───────────┘└┘└──────────────────┘└────┘└─
typ  ───────┘└───────────┘└┘└──────────────────┘└────┘└─
doc  ───────┘             └┘                    └────┘└─
txt  ───────┘             └┘                    └────┘└─
par  ───────┘             └┘                    └────┘└─
pid  ───────┘             └┘                    └───────
st   ────────────────────────────────────────────────┘└─
1528        simp only [list.reverse_core_eq, e.1, e.2, list.map_append, prod.fst,
id                    └──────────────────┘          └─────────────┘
src  ─────┘└─────────┘└──────────────────┘└┘ └──┘ └──┘└─────────────┘└┘        └─
typ  ─────┘└─────────┘└──────────────────┘└┘└──┘└──┘└─────────────┘└┘        └─
doc  ─────┘└─────────┘                    └┘ └──┘ └──┘               └┘        └─
txt  ─────┘└─────────┘                    └┘ └──┘ └──┘               └┘        └─
par  ─────┘└─────────┘                    └┘ └──┘ └──┘               └┘        └─
pid  ────────────────┘                    └┘ └──┘ └──┘               └┘        └─
st   ────────────────────────────────────────────────────────────────────────────
1529          list.map_reverse, list.reverse_cons, list.map, dwrite_eq, e₁, list.map_tail,
id           └──────────────┘  └───────────────┘  └──────┘  └───────┘  └┘  └───────────┘
src  ───────┘└──────────────┘└┘└───────────────┘└┘└──────┘└┘└───────┘└┘  └┘└───────────┘└─
typ  ───────┘└──────────────┘└┘└───────────────┘└┘└──────┘└┘└───────┘└┘└┘└┘└───────────┘└─
doc  ───────┘                └┘                 └┘        └┘         └┘  └┘             └─
txt  ───────┘                └┘                 └┘        └┘         └┘  └┘             └─
par  ───────┘                └┘                 └┘        └┘         └┘  └┘             └─
pid  ───────┘                └┘                 └┘        └┘         └┘  └┘             └─
st   ─────────────────────────────────────────────────────────────────────────────────────
1530          list.tail_repeat, TM2to1.st_write] },
id           └──────────────┘  └─────────────┘
src  ───────┘└──────────────┘└┘└─────────────┘└┘└──
typ  ───────┘└──────────────┘└┘└─────────────┘└┘└──
doc  ───────┘                └┘               └┘└──
txt  ───────┘                └┘               └┘└──
par  ───────┘                └┘               └┘└──
pid  ───────┘                └┘               └────
st   ──────────────────────────────────────────┘└─
1531      { cases T₂ with t T₂,
id               └┘
src  ─────┘└────┘  └────────┘└─
typ  ─────┘└────┘└┘└────────┘└─
doc  ─────┘└────┘  └────────┘└─
txt  ─────┘└────┘  └────────┘└─
par  ─────┘└────┘  └────────┘└─
pid  ───────────┘  └───────────
st   ───────────────────────┘└─
1532        { existsi n+1,
id                   
src  ───────┘└──────┘ └─
typ  ───────┘└──────┘└─
doc  ───────┘└──────┘  └─
txt  ───────┘└──────┘  └─
par  ───────┘└──────┘  └─
pid  ───────────────┘  └──
st   ──────┘└──────────┘└─
1533          simpa only [dwrite_ne _ _ _ _ h, list.reverse_core_eq, e₁, list.repeat_add,
id                       └───────┘           └──────────────────┘  └┘  └─────────────┘
src  ───────┘└──────────┘└───────┘└───────┘ └┘└──────────────────┘└┘  └┘└─────────────┘└─
typ  ───────┘└──────────┘└───────┘└───────┘└┘└──────────────────┘└┘└┘└┘└─────────────┘└─
doc  ───────┘└──────────┘         └───────┘ └┘                    └┘  └┘               └─
txt  ───────┘└──────────┘         └───────┘ └┘                    └┘  └┘               └─
par  ───────┘└──────────┘         └───────┘ └┘                    └┘  └┘               └─
pid  ───────────────────┘         └───────┘ └┘                    └┘  └┘               └─
st   ────────────────────────────────────────────────────────────────────────────────────
1534            tape.write, tape.move, list.reverse_cons, list.map_reverse, list.map_append,
id             └────────┘  └───────┘  └───────────────┘  └──────────────┘  └─────────────┘
src  ─────────┘└────────┘└┘└───────┘└┘└───────────────┘└┘└──────────────┘└┘└─────────────┘└─
typ  ─────────┘└────────┘└┘└───────┘└┘└───────────────┘└┘└──────────────┘└┘└─────────────┘└─
doc  ─────────┘          └┘         └┘                 └┘                └┘               └─
txt  ─────────┘          └┘         └┘                 └┘                └┘               └─
par  ─────────┘          └┘         └┘                 └┘                └┘               └─
pid  ─────────┘          └┘         └┘                 └┘                └┘               └─
st   ───────────────────────────────────────────────────────────────────────────────────────
1535            list.map, list.head, list.tail, list.append_assoc] using
id             └──────┘  └───────┘  └───────┘  └───────────────┘
src  ─────────┘└──────┘└┘└───────┘└┘└───────┘└┘└───────────────┘└───────
typ  ─────────┘└──────┘└┘└───────┘└┘└───────┘└┘└───────────────┘└───────
doc  ─────────┘        └┘         └┘         └┘                 └───────
txt  ─────────┘        └┘         └┘         └┘                 └───────
par  ─────────┘        └┘         └┘         └┘                 └───────
pid  ─────────┘        └┘         └┘         └┘                 └───────
st   ───────────────────────────────────────────────────────────────────
1536            congr_arg (++ [default Γ' k']) e },
id             └───────┘    └─────┘ └┘ └┘  
src  ─────────┘└───────┘└─┘└─────┘└┘  └┘ └──
typ  ─────────┘└───────┘└─┘└─────┘└┘└┘└┘└──
doc  ─────────┘          └─┘             └┘ └──
txt  ─────────┘          └─┘             └┘ └──
par  ─────────┘          └─┘             └┘ └──
pid  ─────────┘          └─┘             └┘ └───
st   ──────────────────────────────────────────┘└─
1537        { existsi n,
id                   
src  ───────┘└──────┘ └─
typ  ───────┘└──────┘└─
doc  ───────┘└──────┘ └─
txt  ───────┘└──────┘ └─
par  ───────┘└──────┘ └─
pid  ───────────────┘ └─
st   ────────────────┘└─
1538          simpa only [dwrite_ne _ _ _ _ h, list.reverse_core_eq, e₁, list.repeat_add,
id                       └───────┘           └──────────────────┘  └┘  └─────────────┘
src  ───────┘└──────────┘└───────┘└───────┘ └┘└──────────────────┘└┘  └┘└─────────────┘└─
typ  ───────┘└──────────┘└───────┘└───────┘└┘└──────────────────┘└┘└┘└┘└─────────────┘└─
doc  ───────┘└──────────┘         └───────┘ └┘                    └┘  └┘               └─
txt  ───────┘└──────────┘         └───────┘ └┘                    └┘  └┘               └─
par  ───────┘└──────────┘         └───────┘ └┘                    └┘  └┘               └─
pid  ───────────────────┘         └───────┘ └┘                    └┘  └┘               └─
st   ────────────────────────────────────────────────────────────────────────────────────
1539            tape.write, tape.move, list.reverse_cons, list.map_reverse, list.map_append,
id             └────────┘  └───────┘  └───────────────┘  └──────────────┘  └─────────────┘
src  ─────────┘└────────┘└┘└───────┘└┘└───────────────┘└┘└──────────────┘└┘└─────────────┘└─
typ  ─────────┘└────────┘└┘└───────┘└┘└───────────────┘└┘└──────────────┘└┘└─────────────┘└─
doc  ─────────┘          └┘         └┘                 └┘                └┘               └─
txt  ─────────┘          └┘         └┘                 └┘                └┘               └─
par  ─────────┘          └┘         └┘                 └┘                └┘               └─
pid  ─────────┘          └┘         └┘                 └┘                └┘               └─
st   ───────────────────────────────────────────────────────────────────────────────────────
1540            list.map, list.head, list.tail, list.append_assoc] using e } } },
id             └──────┘  └───────┘  └───────┘  └───────────────┘        
src  ─────────┘└──────┘└┘└───────┘└┘└───────┘└┘└───────────────┘└──────┘ └───┘
typ  ─────────┘└──────┘└┘└───────┘└┘└───────┘└┘└───────────────┘└──────┘└───┘
doc  ─────────┘        └┘         └┘         └┘                 └──────┘ └───┘
txt  ─────────┘        └┘         └┘         └┘                 └──────┘ └───┘
par  ─────────┘        └┘         └┘         └┘                 └──────┘ └───┘
pid  ─────────┘        └┘         └┘         └┘                 └──────┘ └────┘
st   ────────────────────────────────────────────────────────────────────┘└────┘
1541    have dw := dwrite_self S k,
id                └─────────┘  
src    └─────────┘└─────────┘ 
typ    └─────────┘└─────────┘
doc    └─────────┘            
txt    └─────────┘            
par    └─────────┘            
pid    └─────┘└─┘            
st   ───────────────────────────┘└─
1542    cases T₁ with t T₁; cases eS : S k with s Sk;
id           └┘                        
src    └────┘  └────────┘  └────┘  └─┘  └────────┘
typ    └────┘└┘└────────┘  └────┘  └─┘└────────┘
doc    └────┘  └────────┘  └────┘  └─┘  └────────┘
txt    └────┘  └────────┘  └────┘  └─┘  └────────┘
par    └────┘  └────────┘  └────┘  └─┘  └────────┘
pid           └────────┘         └─┘  └────────┘
st   ────────────────────────────────────────────────
1543      rw eS at e₁ dw; injection e₁ with tk e₁'; cases b,
id          └┘                     └┘                    
src      └─┘  └───────┘  └────────┘  └──────────┘  └────┘
typ      └─┘└┘└───────┘  └────────┘└┘└──────────┘  └────┘
doc      └─┘  └───────┘  └────────┘  └──────────┘  └────┘
txt      └─┘  └───────┘  └────────┘  └──────────┘  └────┘
par      └─┘  └───────┘  └────────┘  └──────────┘  └────┘
pid          └───────┘             └──────────┘       
st   ──────┘└┘└──────────────────────────────────────────┘└─
1544    { -- peek nil
st   ───┘└───────────
1545      simp only [dw, st_write],
id                  └┘  └──────┘
src      └─────────┘  └┘└──────┘
typ      └─────────┘└┘└┘└──────┘
doc      └─────────┘  └┘        
txt      └─────────┘  └┘        
par      └─────────┘  └┘        
pid          └──┘└┘  └┘        
st   ───────────────────────────┘└─
1546      exact ⟨_, [], _, hT, rfl, ea, rfl⟩ },
id                        └┘       └┘  └─┘
src      └────┘ └─┘  └───┘  └┘   └┘  └┘└─┘└┘
typ      └────┘ └─┘  └───┘└┘└┘   └┘└┘└┘└─┘└┘
doc      └────┘ └─┘  └───┘  └┘   └┘  └┘   └┘
txt      └────┘ └─┘  └───┘  └┘   └┘  └┘   └┘
par      └────┘ └─┘  └───┘  └┘   └┘  └┘   └┘
pid            └─┘  └───┘  └┘   └┘  └┘   
st   ──────────────────────────────────────┘└┘
1547    { -- pop nil
st   ───┘└──────────
1548      simp only [dw, st_write, list.tail],
id                  └┘  └──────┘  └───────┘
src      └─────────┘  └┘└──────┘└┘└───────┘
typ      └─────────┘└┘└┘└──────┘└┘└───────┘
doc      └─────────┘  └┘        └┘         
txt      └─────────┘  └┘        └┘         
par      └─────────┘  └┘        └┘         
pid          └──┘└┘  └┘        └┘         
st   ──────────────────────────────────────┘└─
1549      exact ⟨_, [], _, hT, rfl, ea, rfl⟩ },
id                        └┘       └┘  └─┘
src      └────┘ └─┘  └───┘  └┘   └┘  └┘└─┘└┘
typ      └────┘ └─┘  └───┘└┘└┘   └┘└┘└┘└─┘└┘
doc      └────┘ └─┘  └───┘  └┘   └┘  └┘   └┘
txt      └────┘ └─┘  └───┘  └┘   └┘  └┘   └┘
par      └────┘ └─┘  └───┘  └┘   └┘  └┘   └┘
pid            └─┘  └───┘  └┘   └┘  └┘   
st   ──────────────────────────────────────┘└┘
1550    { -- peek cons
st   ───┘└────────────
1551      change t k = stackel.val s at tk,
id                              
src      └─────┘               └────┘
typ      └─────┘            └────┘
doc      └─────┘               └────┘
txt      └─────┘               └────┘
par      └─────┘               └────┘
pid                           └───┘
st   ───────────────────────────────────┘└─
1552      simp only [eS, tk, dw, st_write, TM1.step_aux, tr_st_act, cond, tape.move,
id                  └┘  └┘  └┘  └──────┘  └──────────┘  └───────┘  └──┘  └───────┘
src      └─────────┘  └┘  └┘  └┘└──────┘└┘└──────────┘└┘└───────┘└┘└──┘└┘└───────┘└─
typ      └─────────┘└┘└┘└┘└┘└┘└┘└──────┘└┘└──────────┘└┘└───────┘└┘└──┘└┘└───────┘└─
doc      └─────────┘  └┘  └┘  └┘        └┘└──────────┘└┘         └┘    └┘         └─
txt      └─────────┘  └┘  └┘  └┘        └┘            └┘         └┘    └┘         └─
par      └─────────┘  └┘  └┘  └┘        └┘            └┘         └┘    └┘         └─
pid          └──┘└┘  └┘  └┘  └┘        └┘            └┘         └┘    └┘         └─
st   ───────────────────────────────────────────────────────────────────────────────
1553        list.head, list.tail, list.cons_append],
id         └───────┘  └───────┘  └──────────────┘
src  ─────┘└───────┘└┘└───────┘└┘└──────────────┘
typ  ─────┘└───────┘└┘└───────┘└┘└──────────────┘
doc  ─────┘         └┘         └┘                
txt  ─────┘         └┘         └┘                
par  ─────┘         └┘         └┘                
pid  ─────┘         └┘         └┘                
st   ────────────────────────────────────────────┘└─
1554      exact ⟨_, t::T₁, _, hT, e₁, ea, rfl⟩ },
id                   └┘     └┘  └┘  └┘  └─┘
src      └────┘ └─┘     └───┘  └┘  └┘  └┘└─┘└┘
typ      └────┘ └─┘  └┘└───┘└┘└┘└┘└┘└┘└┘└─┘└┘
doc      └────┘ └─┘     └───┘  └┘  └┘  └┘   └┘
txt      └────┘ └─┘     └───┘  └┘  └┘  └┘   └┘
par      └────┘ └─┘     └───┘  └┘  └┘  └┘   └┘
pid            └─┘     └───┘  └┘  └┘  └┘   
st   ────────────────────────────────────────┘└┘
1555    { -- pop cons
st   ────────────────
1556      change t k = stackel.val s at tk,
id                              
src      └─────┘               └────┘
typ      └─────┘            └────┘
doc      └─────┘               └────┘
txt      └─────┘               └────┘
par      └─────┘               └────┘
pid                           └───┘
st   ───────────────────────────────────┘└─
1557      simp only [tk, st_write, list.tail, TM1.step_aux, tr_st_act, cond,
id                  └┘  └──────┘  └───────┘  └──────────┘  └───────┘  └──┘
src      └─────────┘  └┘└──────┘└┘└───────┘└┘└──────────┘└┘└───────┘└┘└──┘└─
typ      └─────────┘└┘└┘└──────┘└┘└───────┘└┘└──────────┘└┘└───────┘└┘└──┘└─
doc      └─────────┘  └┘        └┘         └┘└──────────┘└┘         └┘    └─
txt      └─────────┘  └┘        └┘         └┘            └┘         └┘    └─
par      └─────────┘  └┘        └┘         └┘            └┘         └┘    └─
pid          └──┘└┘  └┘        └┘         └┘            └┘         └┘    └─
st   ───────────────────────────────────────────────────────────────────────
1558        tape.move, list.cons_append, list.head],
id         └───────┘  └──────────────┘  └───────┘
src  ─────┘└───────┘└┘└──────────────┘└┘└───────┘
typ  ─────┘└───────┘└┘└──────────────┘└┘└───────┘
doc  ─────┘         └┘                └┘         
txt  ─────┘         └┘                └┘         
par  ─────┘         └┘                └┘         
pid  ─────┘         └┘                └┘         
st   ────────────────────────────────────────────┘└─
1559      refine ⟨_, _, _, _, e₁', dwrite_eq _ _ _, rfl⟩,
id                           └─┘  └───────┘        └─┘
src      └─────┘ └──────────┘   └┘└───────┘└──────┘└─┘
typ      └─────┘ └──────────┘└─┘└┘└───────┘└──────┘└─┘
doc      └─────┘ └──────────┘   └┘         └──────┘   
txt      └─────┘ └──────────┘   └┘         └──────┘   
par      └─────┘ └──────────┘   └┘         └──────┘   
pid             └──────────┘   └┘         └──────┘   
st   ─────────────────────────────────────────────────┘└─
1560      intro k', cases hT k' with n e,
id                       └┘ └┘
src      └──────┘  └────┘    └───────┘
typ      └──────┘  └────┘└┘└┘└───────┘
doc      └──────┘  └────┘    └───────┘
txt      └──────┘  └────┘    └───────┘
par      └──────┘  └────┘    └───────┘
pid           └─┘           └───────┘
st   ───────────┘└────────────────────┘└─
1561      by_cases h : k' = k,
id                    └┘   
src      └───────┘ └─┘   
typ      └───────┘ └─┘└┘ 
doc      └───────┘ └─┘   
txt      └───────┘ └─┘   
par      └───────┘ └─┘   
pid               └─┘   
st   ──────────────────────┘└─
1562      { subst k', existsi n+1,
id               └┘          
src        └────┘    └──────┘  
typ        └────┘└┘  └──────┘ 
doc        └────┘    └──────┘  
txt        └────┘    └──────┘  
par        └────┘    └──────┘  
pid                          
st   ─────┘└──────┘└───────────┘└─
1563        simp only [list.reverse_core_eq, eS, e₁', list.append_left_inj,
id                    └──────────────────┘  └┘  └─┘  └──────────────────┘
src        └─────────┘└──────────────────┘└┘  └┘   └┘└──────────────────┘└─
typ        └─────────┘└──────────────────┘└┘└┘└┘└─┘└┘└──────────────────┘└─
doc        └─────────┘                    └┘  └┘   └┘                    └─
txt        └─────────┘                    └┘  └┘   └┘                    └─
par        └─────────┘                    └┘  └┘   └┘                    └─
pid            └──┘└┘                    └┘  └┘   └┘                    └─
st   ──────────────────────────────────────────────────────────────────────
1564          list.map_append, list.map_reverse, list.map, list.reverse_cons,
id           └─────────────┘  └──────────────┘  └──────┘  └───────────────┘
src  ───────┘└─────────────┘└┘└──────────────┘└┘└──────┘└┘└───────────────┘└─
typ  ───────┘└─────────────┘└┘└──────────────┘└┘└──────┘└┘└───────────────┘└─
doc  ───────┘               └┘                └┘        └┘                 └─
txt  ───────┘               └┘                └┘        └┘                 └─
par  ───────┘               └┘                └┘        └┘                 └─
pid  ───────┘               └┘                └┘        └┘                 └─
st   ────────────────────────────────────────────────────────────────────────
1565          list.append_assoc, list.cons_append] at e ⊢,
id           └───────────────┘  └──────────────┘
src  ───────┘└───────────────┘└┘└──────────────┘└──────┘
typ  ───────┘└───────────────┘└┘└──────────────┘└──────┘
doc  ───────┘                 └┘                └──────┘
txt  ───────┘                 └┘                └──────┘
par  ───────┘                 └┘                └──────┘
pid  ───────┘                 └┘                └────┘
st   ──────────────────────────────────────────────────┘└─
1566        simp only [tape.move, tape.write, list.head, list.tail, dwrite_eq],
id                    └───────┘  └────────┘  └───────┘  └───────┘  └───────┘
src        └─────────┘└───────┘└┘└────────┘└┘└───────┘└┘└───────┘└┘└───────┘
typ        └─────────┘└───────┘└┘└────────┘└┘└───────┘└┘└───────┘└┘└───────┘
doc        └─────────┘         └┘          └┘         └┘         └┘         
txt        └─────────┘         └┘          └┘         └┘         └┘         
par        └─────────┘         └┘          └┘         └┘         └┘         
pid            └──┘└┘         └┘          └┘         └┘         └┘         
st   ───────────────────────────────────────────────────────────────────────┘└─
1567        rw [e.2.2]; refl },
id             
src        └──┘ └───┘  └───┘
typ        └──┘└───┘  └───┘
doc        └──┘ └───┘  └───┘
txt        └──┘ └───┘  └───┘
par        └──┘ └───┘  └───┘
pid          └┘ └───┘      
st   ────────────┘└─┘└─────┘└┘
1568      { existsi n, simpa only [dwrite_ne _ _ _ _ h, list.map, list.head, list.tail,
id                               └───────┘           └──────┘  └───────┘  └───────┘
src        └──────┘   └──────────┘└───────┘└───────┘ └┘└──────┘└┘└───────┘└┘└───────┘└─
typ        └──────┘  └──────────┘└───────┘└───────┘└┘└──────┘└┘└───────┘└┘└───────┘└─
doc        └──────┘   └──────────┘         └───────┘ └┘        └┘         └┘         └─
txt        └──────┘   └──────────┘         └───────┘ └┘        └┘         └┘         └─
par        └──────┘   └──────────┘         └───────┘ └┘        └┘         └┘         └─
pid                       └──┘└┘         └───────┘ └┘        └┘         └┘         └─
st   ──────────────┘└──────────────────────────────────────────────────────────────────
1569          list.reverse_core, list.map_reverse_core, tape.move, tape.write] using e } },
id           └───────────────┘  └───────────────────┘  └───────┘  └────────┘        
src  ───────┘└───────────────┘└┘└───────────────────┘└┘└───────┘└┘└────────┘└──────┘ 
typ  ───────┘└───────────────┘└┘└───────────────────┘└┘└───────┘└┘└────────┘└──────┘
doc  ───────┘                 └┘                     └┘         └┘          └──────┘ 
txt  ───────┘                 └┘                     └┘         └┘          └──────┘ 
par  ───────┘                 └┘                     └┘         └┘          └──────┘ 
pid  ───────┘                 └┘                     └┘         └┘          └────┘ 
st   ────────────────────────────────────────────────────────────────────────────────┘└────
1570  end
st   ──┘
1571  
1572  theorem tr_respects_aux₃ {k q v}
1573    {S : Π k, list (Γ k)} {T : list Γ'}
id              └──┘           └──┘ └┘
src              └──┘             └──┘ └┘
typ             └──┘           └──┘ └┘
1574    (hT : ∀ k, tr_stk (S k) (T.map (λ (a : Γ'), a k))) :
id               └────┘      └──┘         └┘    
src               └────┘         └──┘         └┘
typ              └────┘      └──┘         └┘    
1575    ∀ (T₁ : list Γ') {T₂ : list Γ'} {a : Γ'} {S₁}
id            └──┘ └┘        └──┘ └┘       └┘   └┘
src            └──┘ └┘        └──┘ └┘       └┘
typ           └──┘ └┘        └──┘ └┘       └┘   └┘
1576      (e : T = T₁.reverse_core (a :: T₂))
id              └┘└───────────┘   └┘ └┘
src                └───────────┘    └┘
typ             └┘└───────────┘   └┘ └┘
1577      (ha : (a k).is_bottom = ff)
id                └───────┘   └┘
src                 └───────┘   └┘
typ               └───────┘   └┘
1578      (e₁ : T₁.map (λ (a : Γ'), a k) = list.map stackel.val S₁),
id             └┘└──┘         └┘       └──────┘ └─────────┘ └┘
src              └──┘         └┘         └──────┘ └─────────┘
typ            └┘└──┘         └┘       └──────┘ └─────────┘ └┘
1579      reaches₀ (TM1.step tr)
id       └──────┘  └──────┘ └┘
src      └──────┘  └──────┘ └┘
typ      └──────┘  └──────┘ └┘
1580        ⟨some (ret k q), v, (a, T₁ ++ [stackel.bottom], T₂)⟩
id          └──┘  └─┘         └┘ └┘ └────────────┘  └┘
src         └──┘  └─┘                └┘ └────────────┘
typ         └──┘  └─┘         └┘ └┘ └────────────┘  └┘
1581        ⟨some (ret k q), v, (stackel.bottom, [], T)⟩
id          └──┘  └─┘       └────────────┘  └┘  
src         └──┘  └─┘          └────────────┘  └┘
typ         └──┘  └─┘       └────────────┘  └┘  
1582  | [] T₂ a S₁ e ha e₁ := reaches₀.single (by simp only [ha, e, TM1.step,
id     └┘                    └─────────────┘                └┘    └──────┘
src    └┘                    └─────────────┘     └─────────┘  └┘ └┘└──────┘└─
typ    └┘                    └─────────────┘     └─────────┘└┘└┘└┘└──────┘└─
doc                                              └─────────┘  └┘ └┘        └─
txt                                              └─────────┘  └┘ └┘        └─
par                                              └─────────┘  └┘ └┘        └─
pid                                                  └──┘└┘  └┘ └┘        └─
st                                              └────────────────────────────
1583      option.mem_def, tr, TM1.step_aux] {constructor_eq:=ff}; refl)
id       └────────────┘  └┘  └──────────┘                   └┘
src  ───┘└────────────┘└┘└┘└┘└──────────┘└┘ └──────────────┘└┘  └──┘
typ  ───┘└────────────┘└┘└┘└┘└──────────┘└┘ └──────────────┘└┘  └──┘
doc  ───┘              └┘  └┘└──────────┘└┘ └──────────────┘    └──┘
txt  ───┘              └┘  └┘            └┘ └──────────────┘    └──┘
par  ───┘              └┘  └┘            └┘ └──────────────┘    └──┘
pid  ───┘              └┘  └┘             └──────────────┘  
st   ───────────────────────────────────────────────────────────────┘
1584  | (b :: T₁) T₂ a (s :: S₁) e ha e₁ := begin
id        └┘             └┘
src       └┘             └┘
typ       └┘             └┘
st                                         └─────
1585      unfold list.map at e₁, injection e₁ with es e₁,
id                                        └┘
src      └───────────────────┘  └────────┘  └─────────┘
typ      └───────────────────┘  └────────┘└┘└─────────┘
doc      └───────────────────┘  └────────┘  └─────────┘
txt      └───────────────────┘  └────────┘  └─────────┘
par      └───────────────────┘  └────────┘  └─────────┘
pid            └───────┘└────┘             └─────────┘
st   ────────────────────────┘└───────────────────────┘└─
1586      refine reaches₀.head _ (tr_respects_aux₃ T₁ e (by rw es; refl) e₁),
id              └───────────┘    └──────────────┘ └┘         └┘        └┘
src      └─────┘└───────────┘└─┘                       └─┘  └┘└──┘└┘  
typ      └─────┘└───────────┘└─┘ └──────────────┘└┘   └─┘└┘└┘└──┘└┘└┘
doc      └─────┘             └─┘                       └─┘  └┘└──┘└┘  
txt      └─────┘             └─┘                       └─┘  └┘└──┘└┘  
par      └─────┘             └─┘                       └─┘  └┘└──┘└┘  
pid                         └─┘                       └──┘  └──────┘  
st   ────────────────────────────────────────────────────┘└──────────┘└───┘└─
1587      simp only [ha, option.mem_def, TM1.step, tr, TM1.step_aux], refl
id                  └┘  └────────────┘  └──────┘  └┘  └──────────┘
src      └─────────┘  └┘└────────────┘└┘└──────┘└┘└┘└┘└──────────┘  └────
typ      └─────────┘└┘└┘└────────────┘└┘└──────┘└┘└┘└┘└──────────┘  └────
doc      └─────────┘  └┘              └┘        └┘  └┘└──────────┘  └────
txt      └─────────┘  └┘              └┘        └┘  └┘              └────
par      └─────────┘  └┘              └┘        └┘  └┘              └────
pid          └──┘└┘  └┘              └┘        └┘  └┘                  
st   ─────────────────────────────────────────────────────────────┘└──────
1588    end
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
1589  
1590  theorem tr_respects_aux {q v T k} {S : Π k, list (Γ k)}
id                                              └──┘   
src                                              └──┘
typ                                             └──┘   
1591    (hT : ∀ (k : K), tr_stk (S k) (list.map (λ (a : Γ'), a k) T))
id                     └────┘      └──────┘         └┘      
src                     └────┘        └──────┘         └┘
typ                    └────┘      └──────┘         └┘      
1592    (o : st_act k)
id          └────┘ 
src         └────┘
typ         └────┘ 
1593    (IH : ∀ {v : σ} {S : Π (k : K), list (Γ k)} {T : list Γ'},
id                                  └──┘           └──┘ └┘
src                                    └──┘             └──┘ └┘
typ                                 └──┘           └──┘ └┘
1594      (∀ (k : K), tr_stk (S k) (list.map (λ (a : Γ'), a k) T)) →
id                 └────┘      └──────┘         └┘      
src                  └────┘        └──────┘         └┘
typ                └────┘      └──────┘         └┘      
1595      (∃ b, tr_cfg (TM2.step_aux q v S) b ∧
id          └────┘  └──────────┘      
src          └────┘  └──────────┘          
typ         └────┘  └──────────┘      
1596        reaches (TM1.step tr) (TM1.step_aux (tr_normal q) v (stackel.bottom, [], T)) b)) :
id         └─────┘  └──────┘ └┘   └──────────┘  └───────┘    └────────────┘  └┘     
src        └─────┘  └──────┘ └┘   └──────────┘  └───────┘      └────────────┘  └┘
typ        └─────┘  └──────┘ └┘   └──────────┘  └───────┘    └────────────┘  └┘     
doc                               └──────────┘
1597    ∃ b, tr_cfg (TM2.step_aux (st_run o q) v S) b ∧
id       └────┘  └──────────┘  └────┘        
src       └────┘  └──────────┘  └────┘             
typ      └────┘  └──────────┘  └────┘        
1598      reaches (TM1.step tr) (TM1.step_aux (tr_normal (st_run o q))
id       └─────┘  └──────┘ └┘   └──────────┘  └───────┘  └────┘  
src      └─────┘  └──────┘ └┘   └──────────┘  └───────┘  └────┘
typ      └─────┘  └──────┘ └┘   └──────────┘  └───────┘  └────┘  
doc                             └──────────┘
1599        v (stackel.bottom, [], T)) b :=
id          └────────────┘  └┘     
src          └────────────┘  └┘
typ         └────────────┘  └┘     
1600  begin
st   └─────
1601    rcases hT k with ⟨n, hTk⟩,
id            └┘ 
src    └─────┘   └────────────┘
typ    └─────┘└┘└────────────┘
doc    └─────┘   └────────────┘
txt    └─────┘   └────────────┘
par    └─────┘   └────────────┘
pid             └────────────┘
st   ──────────────────────────┘└─
1602    simp only [tr_normal_run],
id                └───────────┘
src    └─────────┘└───────────┘
typ    └─────────┘└───────────┘
doc    └─────────┘             
txt    └─────────┘             
par    └─────────┘             
pid        └──┘└┘             
st   ──────────────────────────┘└─
1603    rcases tr_respects_aux₁ M o q v _ hTk with ⟨a, T₁, T₂, rfl, ea, e₁, e₂, hgo⟩,
id            └──────────────┘       └─┘
src    └─────┘└──────────────┘    └─┘   └─────────────────────────────────────┘
typ    └─────┘└──────────────┘└─┘└─┘└─────────────────────────────────────┘
doc    └─────┘                    └─┘   └─────────────────────────────────────┘
txt    └─────┘                    └─┘   └─────────────────────────────────────┘
par    └─────┘                    └─┘   └─────────────────────────────────────┘
pid                              └─┘   └─────────────────────────────────────┘
st   ─────────────────────────────────────────────────────────────────────────────┘└─
1604    rcases tr_respects_aux₂ M hT e₁ ea _ with ⟨b, T₁', T₂', hT', e₁', eb, hrun⟩,
id            └──────────────┘  └┘ └┘ └┘
src    └─────┘└──────────────┘       └───────────────────────────────────────┘
typ    └─────┘└──────────────┘└┘└┘└┘└───────────────────────────────────────┘
doc    └─────┘                       └───────────────────────────────────────┘
txt    └─────┘                       └───────────────────────────────────────┘
par    └─────┘                       └───────────────────────────────────────┘
pid                                 └───────────────────────────────────────┘
st   ────────────────────────────────────────────────────────────────────────────┘└─
1605    have hret := tr_respects_aux₃ M hT' _ rfl (by rw eb; refl) e₁',
id                  └──────────────┘  └─┘   └─┘        └┘        └─┘
src    └───────────┘└──────────────┘    └─┘└─┘   └─┘  └┘└──┘└┘
typ    └───────────┘└──────────────┘└─┘└─┘└─┘   └─┘└┘└┘└──┘└┘└─┘
doc    └───────────┘                    └─┘      └─┘  └┘└──┘└┘
txt    └───────────┘                    └─┘      └─┘  └┘└──┘└┘
par    └───────────┘                    └─┘      └─┘  └┘└──┘└┘
pid    └───────┘└─┘                    └─┘      └──┘  └──────┘
st   ──────────────────────────────────────────────┘└──────────┘└───┘
1606    have := hgo.tail' rfl,
1607    simp only [ea, tr, TM1.step_aux] at this,
1608    rw [hrun, TM1.step_aux] at this,
id               └──────────┘
src             └──────────┘
typ             └──────────┘
doc             └──────────┘
txt             
par             
pid             
st              └───────────┘
1609    rcases IH hT' with ⟨c, gc, rc⟩,
1610    simp only [step_run],
1611    refine ⟨c, gc, (this.to₀.trans hret _ (trans_gen.head' rfl rc)).to_refl⟩
1612  end
st   └─┘
1613  
1614  local attribute [simp] respects TM2.step TM2.step_aux tr_normal
id                          └──────┘ └──────┘ └──────────┘ └───────┘
src                         └──────┘ └──────┘ └──────────┘ └───────┘
typ                         └──────┘ └──────┘ └──────────┘ └───────┘
doc                   └──┘
1615  
1616  theorem tr_respects : respects (TM2.step M) (TM1.step tr) tr_cfg :=
id                         └──────┘  └──────┘    └──────┘ └┘  └────┘
src                        └──────┘  └──────┘     └──────┘ └┘  └────┘
typ                        └──────┘  └──────┘    └──────┘ └┘  └────┘
1617  λ c₁ c₂ h, begin
id     └┘ └┘ 
typ    └┘ └┘ 
st              └─────
1618    cases h with l v S L hT, clear h,
id           
src    └────┘ └──────────────┘  └─────┘
typ    └────┘└──────────────┘  └─────┘
doc    └────┘ └──────────────┘  └─────┘
txt    └────┘ └──────────────┘  └─────┘
par    └────┘ └──────────────┘  └─────┘
pid          └──────────────┘       └┘
st   ────────────────────────┘└───────┘└─
1619    cases l, {constructor},
id           
src    └────┘
typ    └────┘
doc    └────┘
txt    └────┘
par    └────┘
pid         
st   ────────┘└┘            └┘
1620    simp only [TM2.step, respects, option.map_some'],
1621    suffices : ∃ b, _ ∧ reaches (TM1.step (tr M)) _ _,
1622    from let ⟨b, c, r⟩ := this in ⟨b, c, trans_gen.head' rfl r⟩,
1623    rw [tr],
1624    revert v S L hT, refine stmt_st_rec _ _ _ _ _ (M l); intros,
id                                                      
typ                                                     
1625    { exact tr_respects_aux M hT s @IH },
st                                        └┘
1626    { exact IH hT },
st                   └┘
1627    { unfold TM2.step_aux tr_normal TM1.step_aux,
1628      cases p v; [exact IH₂ hT, exact IH₁ hT] },
id              
typ             
1629    { exact ⟨_, ⟨hT⟩, refl_trans_gen.refl⟩ },
st                                            └┘
1630    { exact ⟨_, ⟨hT⟩, refl_trans_gen.refl⟩ }
st                                            └─
1631  end
st   ──┘
1632  
1633  theorem tr_cfg_init (k) (L : list (Γ k)) :
id                                └┘     
src                               └┘
typ                               └┘     
1634    tr_cfg (TM2.init k L) (TM1.init (tr_init k L)) :=
id                                             
typ                                            
1635  ⟨λ k', begin
id      └┘
typ     └┘
1636    unfold tr_init,
1637    cases e : L.reverse with a L',
1638    { cases list.reverse_eq_nil.1 e, rw dwrite_self, exact ⟨0, rfl⟩ },
st                                                                     └┘
1639    by_cases k' = k,
id              └┘   
typ             └┘   
1640    { subst k', existsi 0,
id             └┘
typ            └┘
1641      simp only [list.tail, dwrite_eq, list.reverse_core_eq,
1642        list.repeat, tr_init, list.map, list.map_map, (∘), list.map_id' (λ _, rfl)],
id                                                                            
typ                                                                           
1643      rw [← list.map_reverse, e], refl },
st                                        └┘
1644    { existsi L'.length + 1,
1645      simp only [dwrite_ne _ _ _ _ h, list.tail, tr_init, list.map_map,
id                                    
typ                                   
1646        list.map, list.map_append, list.repeat_add, (∘),
1647        list.map_const] {constructor_eq:=ff},
id                                          └┘
src                                         └┘
typ                                         └┘
1648      refl }
st            └─
1649  end⟩
st   ──┘
1650  
1651  theorem tr_eval_dom (k) (L : list (Γ k)) :
id                                └┘     
src                               └┘
typ                               └┘     
1652    (TM1.eval tr (tr_init k L)).dom ↔ (TM2.eval M k L).dom :=
id                                                 
src                                    
typ                                                
1653  tr_eval_dom tr_respects (tr_cfg_init _ _)
1654  
1655  theorem tr_eval (k) (L : list (Γ k)) {L₁ L₂}
id                            └┘     
src                           └┘
typ                           └┘     
1656    (H₁ : L₁ ∈ TM1.eval tr (tr_init k L))
id                                     
typ                                    
1657    (H₂ : L₂ ∈ TM2.eval M k L) :
id                           
typ                          
1658    ∃ S : ∀ k, list (Γ k),
id                 └┘     
src                └┘
typ                └┘     
1659      (∀ k', tr_stk (S k') (L₁.map (λ a, a k'))) ∧ S k = L₂ :=
id          └┘            └┘                └┘            
typ         └┘            └┘                └┘            
1660  begin
1661    rcases (roption.mem_map_iff _).1 H₁ with ⟨c₁, h₁, rfl⟩,
1662    rcases (roption.mem_map_iff _).1 H₂ with ⟨c₂, h₂, rfl⟩,
1663    rcases tr_eval (tr_respects M) (tr_cfg_init M k L) h₂
id                                                    
typ                                                   
1664      with ⟨_, ⟨q, v, S, L₁', hT⟩, h₃⟩,
1665    cases roption.mem_unique h₁ h₃,
1666    exact ⟨S, hT, rfl⟩
1667  end
st   └─┘
1668  
1669  variables [fintype K] [∀ k, fintype (Γ k)] [fintype σ]
id              └──┘           └─────┘        └─────┘
src             └──┘            └─────┘         └─────┘
typ             └──┘           └─────┘        └─────┘
doc             └──┘            └─────┘         └─────┘
1670  open_locale classical
1671  local attribute [simp] TM2.stmts₁_self
id                          └─────────────┘
src                         └─────────────┘
typ                         └─────────────┘
doc                   └──┘
1672  
1673  noncomputable def tr_stmts₁ : stmt₂ → finset Λ'
id                                 └───┘  └────┘ └┘
src                                └───┘   └────┘ └┘
typ                                └───┘  └────┘ └┘
doc                                └───┘   └────┘
1674  | Q@(TM2.stmt.push k f q)     := {go k (st_act.push f) q, ret k q} ∪ tr_stmts₁ q
id        └───────────┘            └┘    └─────────┘      └─┘       └───────┘
src       └───────────┘               └┘    └─────────┘      └─┘      
typ       └───────────┘            └┘    └─────────┘      └─┘       └───────┘
1675  | Q@(TM2.stmt.peek k f q)     := {go k (st_act.pop ff f) q, ret k q} ∪ tr_stmts₁ q
id        └───────────┘            └┘    └────────┘ └┘      └─┘       └───────┘
src       └───────────┘               └┘    └────────┘ └┘      └─┘      
typ       └───────────┘            └┘    └────────┘ └┘      └─┘       └───────┘
1676  | Q@(TM2.stmt.pop k f q)      := {go k (st_act.pop tt f) q, ret k q} ∪ tr_stmts₁ q
id        └──────────┘             └┘    └────────┘ └┘      └─┘       └───────┘
src       └──────────┘                └┘    └────────┘ └┘      └─┘      
typ       └──────────┘             └┘    └────────┘ └┘      └─┘       └───────┘
1677  | Q@(TM2.stmt.load a q)       := tr_stmts₁ q
id        └───────────┘              └───────┘
src       └───────────┘
typ       └───────────┘              └───────┘
1678  | Q@(TM2.stmt.branch f q₁ q₂) := tr_stmts₁ q₁ ∪ tr_stmts₁ q₂
id        └─────────────┘   └┘ └┘     └───────┘     └───────┘
src       └─────────────┘                          
typ       └─────────────┘   └┘ └┘     └───────┘     └───────┘
1679  | _                           := ∅
id                                    
src                                   
typ                                   
1680  
1681  theorem tr_stmts₁_run {k s q} : tr_stmts₁ (st_run s q) = {go k s q, ret k q} ∪ tr_stmts₁ q :=
id                                   └───────┘  └────┘     └┘    └─┘     └───────┘ 
src                                  └───────┘  └────┘       └┘       └─┘       └───────┘
typ                                  └───────┘  └────┘     └┘    └─┘     └───────┘ 
1682  by rcases s with _|_|_; unfold tr_stmts₁ st_run
id             
src            
typ           
doc            
txt            
par            
pid             
st     └┘      └┘          └┘
1683  
1684  noncomputable def tr_supp (S : finset Λ) : finset Λ' :=
id                                  └────┘     └────┘ └┘
src                                 └────┘      └────┘ └┘
typ                                 └────┘     └────┘ └┘
doc                                 └────┘      └────┘
1685  S.bind (λ l, insert (normal l) (tr_stmts₁ (M l)))
id   └───┘      └────┘  └────┘    └───────┘   
src   └───┘       └────┘  └────┘     └───────┘
typ  └───┘      └────┘  └────┘    └───────┘   
doc   └───┘
1686  
1687  local attribute [simp] tr_stmts₁ tr_stmts₁_run supports_run
id                          └───────┘               └──────────┘
src                         └───────┘               └──────────┘
typ                         └───────┘               └──────────┘
doc                   └──┘
1688    tr_normal_run TM1.supports_stmt TM2.supports_stmt
id     └───────────┘ └───────────────┘ └───────────────┘
src    └───────────┘ └───────────────┘ └───────────────┘
typ    └───────────┘ └───────────────┘ └───────────────┘
1689  
1690  theorem tr_supports {S} (ss : TM2.supports M S) :
id                                 └──────────┘  
src                                └──────────┘
typ                                └──────────┘  
1691    TM1.supports tr (tr_supp S) :=
id     └──────────┘ └┘  └─────┘ 
src    └──────────┘ └┘  └─────┘
typ    └──────────┘ └┘  └─────┘ 
doc    └──────────┘
1692  ⟨finset.mem_bind.2 ⟨_, ss.1, finset.mem_insert.2 $ or.inl rfl⟩,
id    └─────────────┘      └┘   └───────────────┘    └────┘ └─┘
src   └─────────────┘           └───────────────┘    └────┘ └─┘
typ   └─────────────┘      └┘   └───────────────┘    └────┘ └─┘
1693  λ l' h, begin
id     └┘ 
typ    └┘ 
st           └─────
1694    suffices : ∀ q (ss' : TM2.supports_stmt S q)
id                           └───────────────┘
src                          └───────────────┘
typ                          └───────────────┘
st   ─┘                     └───────────────┘  
1695      (sub : ∀ x ∈ tr_stmts₁ M q, x ∈ tr_supp M S),
st                   └───────┘  └┘   └─────┘   
1696      TM1.supports_stmt (tr_supp M S) (tr_normal q) ∧
id                                        └───────┘    
src                                       └───────┘    
typ                                       └───────┘    
st       └───────────────┘ └──────┘    └────────┘   
1697      (∀ l' ∈ tr_stmts₁ M q, TM1.supports_stmt (tr_supp M S) (tr M l')),
id               └──┘  └─┘      └───────────────┘  └──┘          └┘ 
src              └──┘  └─┘      └───────────────┘  └──┘          └┘
typ              └──┘  └─┘      └───────────────┘  └──┘          └┘ 
st       └┘      └┘   └┘    └┘ └───────────┘ └─┘ └─┘          └─┘  └┘
1698    { rcases finset.mem_bind.1 h with ⟨l, lS, h⟩,
1699      have := this _ (ss.2 l lS) (λ x hx,
id                            
typ                           
1700        finset.mem_bind.2 ⟨_, lS, finset.mem_insert_of_mem hx⟩),
1701      rcases finset.mem_insert.1 h with rfl | h;
1702      [exact this.1, exact this.2 _ h] },
st                                        └┘
1703    clear h l', refine stmt_st_rec _ _ _ _ _; intros,
1704    { -- stack op
1705      rw TM2to1.supports_run at ss',
1706      simp only [TM2to1.tr_stmts₁_run, finset.mem_union,
1707        finset.has_insert_eq_insert, finset.insert_empty_eq_singleton,
1708        finset.mem_insert, finset.mem_singleton] at sub,
1709      have hgo := sub _ (or.inl $ or.inr rfl),
1710      have hret := sub _ (or.inl $ or.inl rfl),
1711      cases IH ss' (λ x hx, sub x $ or.inr hx) with IH₁ IH₂,
1712      refine ⟨by simp only [tr_normal_run, TM1.supports_stmt]; intros; exact hgo, λ l h, _⟩,
1713      rw [tr_stmts₁_run] at h,
1714      simp only [TM2to1.tr_stmts₁_run, finset.mem_union,
1715        finset.has_insert_eq_insert, finset.insert_empty_eq_singleton,
1716        finset.mem_insert, finset.mem_singleton] at h,
1717      rcases h with ⟨rfl | rfl⟩ | h,
1718      { unfold TM1.supports_stmt TM2to1.tr,
1719        exact ⟨IH₁, λ _ _, hret⟩ },
id                         
typ                        
st                                  └┘
1720      { unfold TM1.supports_stmt TM2to1.tr,
1721        rcases s with _|_|_,
1722        { exact ⟨λ _ _, hret, λ _ _, hgo⟩ },
id                                  
typ                                 
st                                           └┘
1723        { exact ⟨λ _ _, hret, λ _ _, hgo⟩ },
id                                  
typ                                 
st                                           └┘
1724        { exact ⟨⟨λ _ _, hret, λ _ _, hret⟩, λ _ _, hgo⟩ } },
id                                                
typ                                               
st                                                          └──┘
1725      { exact IH₂ _ h } },
st                       └──┘
1726    { -- load
1727      unfold TM2to1.tr_stmts₁ at ss' sub ⊢,
1728      exact IH ss' sub },
st                        └┘
1729    { -- branch
1730      unfold TM2to1.tr_stmts₁ at sub,
1731      cases IH₁ ss'.1 (λ x hx, sub x $ finset.mem_union_left _ hx) with IH₁₁ IH₁₂,
1732      cases IH₂ ss'.2 (λ x hx, sub x $ finset.mem_union_right _ hx) with IH₂₁ IH₂₂,
1733      refine ⟨⟨IH₁₁, IH₂₁⟩, λ l h, _⟩,
1734      rw [tr_stmts₁] at h,
1735      rcases finset.mem_union.1 h with h | h;
1736      [exact IH₁₂ _ h, exact IH₂₂ _ h] },
st                                        └┘
1737    { -- goto
1738      rw tr_stmts₁, unfold TM2to1.tr_normal TM1.supports_stmt,
1739      unfold TM2.supports_stmt at ss',
1740      exact ⟨λ _ v, finset.mem_bind.2 ⟨_, ss' v, finset.mem_insert_self _ _⟩, λ _, false.elim⟩ },
id                  
typ                 
st                                                                                                └┘
1741    { exact ⟨trivial, λ _, false.elim⟩ } -- halt
id              └─────┘
src             └─────┘
typ             └─────┘
st                                        └┘
1742  end⟩
st   └─┘
1743  
1744  end
1745  
1746  end TM2to1
1747  
1748  end turing